X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=869cc25f614dfd897163f4c226a36af88758db16;hb=296ba6e16420b89723d1a5b1217d6ecfc2fb0c7d;hp=1dc9abb829f95386fe9fbd082edc5dcee1f3467a;hpb=766a6ccd27b2004800eea73eeeafea7bdee8ed5c;p=cparser diff --git a/parser.c b/parser.c index 1dc9abb..869cc25 100644 --- a/parser.c +++ b/parser.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -27,7 +28,7 @@ #include "parser.h" #include "diagnostic.h" #include "format_check.h" -#include "lexer.h" +#include "preprocessor.h" #include "symbol_t.h" #include "token_t.h" #include "types.h" @@ -40,6 +41,7 @@ #include "walk.h" #include "warning.h" #include "printer.h" +#include "ast2firm.h" #include "adt/bitfiddle.h" #include "adt/error.h" #include "adt/array.h" @@ -59,7 +61,7 @@ struct declaration_specifiers_t { storage_class_t storage_class; unsigned char alignment; /**< Alignment, 0 if not set. */ bool is_inline : 1; - bool thread_local : 1; /**< GCC __thread */ + bool thread_local : 1; attribute_t *attributes; /**< list of attributes */ type_t *type; }; @@ -138,9 +140,6 @@ static elf_visibility_tag_t default_visibility = ELF_VISIBILITY_DEFAULT; #define POP_EXTENSION() \ ((void)(in_gcc_extension = old_gcc_extension)) -/** special symbol used for anonymous entities. */ -static symbol_t *sym_anonymous = NULL; - /** The token anchor set */ static unsigned short token_anchor_set[T_LAST_TOKEN]; @@ -185,7 +184,7 @@ static void semantic_comparison(binary_expression_t *expression); case T_static: \ case T_auto: \ case T_register: \ - case T___thread: + case T__Thread_local: #define TYPE_QUALIFIERS \ case T_const: \ @@ -247,15 +246,14 @@ 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__Alignof: \ case T___FUNCDNAME__: \ case T___FUNCSIG__: \ case T___PRETTY_FUNCTION__: \ - case T___alignof__: \ case T___builtin_classify_type: \ case T___builtin_constant_p: \ case T___builtin_isgreater: \ @@ -299,7 +297,6 @@ static size_t get_statement_struct_size(statement_kind_t kind) [STATEMENT_GOTO] = sizeof(goto_statement_t), [STATEMENT_LABEL] = sizeof(label_statement_t), [STATEMENT_CASE_LABEL] = sizeof(case_label_statement_t), - [STATEMENT_WHILE] = sizeof(while_statement_t), [STATEMENT_DO_WHILE] = sizeof(do_while_statement_t), [STATEMENT_FOR] = sizeof(for_statement_t), [STATEMENT_ASM] = sizeof(asm_statement_t), @@ -326,6 +323,7 @@ static size_t get_expression_struct_size(expression_kind_t kind) [EXPR_LITERAL_INTEGER] = sizeof(literal_expression_t), [EXPR_LITERAL_FLOATINGPOINT] = sizeof(literal_expression_t), [EXPR_LITERAL_CHARACTER] = sizeof(string_literal_expression_t), + [EXPR_LITERAL_MS_NOOP] = sizeof(literal_expression_t), [EXPR_STRING_LITERAL] = sizeof(string_literal_expression_t), [EXPR_COMPOUND_LITERAL] = sizeof(compound_literal_expression_t), [EXPR_CALL] = sizeof(call_expression_t), @@ -427,7 +425,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_STRING] = sizeof(initializer_value_t), [INITIALIZER_LIST] = sizeof(initializer_list_t), [INITIALIZER_DESIGNATOR] = sizeof(initializer_designator_t) }; @@ -470,8 +468,8 @@ static size_t label_top(void) static inline void next_token(void) { token = lookahead_buffer[lookahead_bufpos]; - lookahead_buffer[lookahead_bufpos] = lexer_token; - lexer_next_token(); + lookahead_buffer[lookahead_bufpos] = pp_token; + next_preprocessing_token(); lookahead_bufpos = (lookahead_bufpos + 1) % MAX_LOOKAHEAD; @@ -481,12 +479,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; @@ -1038,51 +1041,49 @@ static void append_string(string_t const *const s) obstack_grow(&ast_obstack, s->begin, s->size); } -static string_t finish_string(void) +static string_t finish_string(string_encoding_t const enc) { 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 }; + return (string_t){ string, size, enc }; } -static string_t concat_string_literals(string_encoding_t *const out_enc) +static string_t concat_string_literals(void) { assert(token.kind == T_STRING_LITERAL); - string_t result; - string_encoding_t enc = token.string.encoding; + string_t result; if (look_ahead(1)->kind == T_STRING_LITERAL) { - append_string(&token.string.string); + 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.string.encoding != STRING_ENCODING_CHAR) { - enc = token.string.encoding; + if (token.literal.string.encoding != STRING_ENCODING_CHAR) { + enc = token.literal.string.encoding; } - append_string(&token.string.string); + append_string(&token.literal.string); eat(T_STRING_LITERAL); } while (token.kind == T_STRING_LITERAL); - result = finish_string(); + result = finish_string(enc); } else { - result = token.string.string; + result = token.literal.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 }; + return (string_t){ "", 0, STRING_ENCODING_CHAR }; - string_encoding_t enc; source_position_t const pos = *HERE; - string_t const res = concat_string_literals(&enc); + string_t const res = concat_string_literals(); - if (enc != STRING_ENCODING_CHAR) { + if (res.encoding != STRING_ENCODING_CHAR) { errorf(&pos, "expected plain string literal, got wide string literal"); } @@ -1176,6 +1177,12 @@ static attribute_t *parse_attribute_gnu_single(void) char const *const name = symbol->string; for (kind = ATTRIBUTE_GNU_FIRST;; ++kind) { if (kind > ATTRIBUTE_GNU_LAST) { + /* special case for "__const" */ + if (token.kind == T_const) { + kind = ATTRIBUTE_GNU_CONST; + break; + } + warningf(WARN_ATTRIBUTE, HERE, "unknown attribute '%s' ignored", name); /* TODO: we should still save the attribute in the list... */ kind = ATTRIBUTE_UNKNOWN; @@ -1543,18 +1550,6 @@ static designator_t *parse_designation(void) } } -static initializer_t *initializer_from_string(array_type_t *const type, string_encoding_t const enc, string_t const *const string) -{ - /* TODO: check len vs. size of array type */ - (void) type; - - initializer_t *initializer = allocate_initializer_zero(INITIALIZER_STRING); - initializer->string.encoding = enc; - initializer->string.string = *string; - - return initializer; -} - /** * Build an initializer from a given expression. */ @@ -1563,36 +1558,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 && expression->kind == EXPR_STRING_LITERAL) { - switch (expression->string_literal.encoding) { - case STRING_ENCODING_CHAR: { - atomic_type_kind_t const akind = element_type->atomic.akind; - if (akind == ATOMIC_TYPE_CHAR - || akind == ATOMIC_TYPE_SCHAR - || akind == ATOMIC_TYPE_UCHAR) { - goto make_string_init; - } - 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; + } - 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: - return initializer_from_string(array_type, expression->string_literal.encoding, &expression->string_literal.value); - } - 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; + } } } @@ -1970,6 +1961,8 @@ static initializer_t *parse_sub_initializer(type_path_t *path, return create_empty_initializer(); } + initializer_t *result = NULL; + type_t *orig_type = path->top_type; type_t *type = NULL; @@ -2073,14 +2066,14 @@ finish_designator: /* handle { "string" } special case */ if (expression->kind == EXPR_STRING_LITERAL && outer_type != NULL) { - sub = initializer_from_expression(outer_type, expression); - if (sub != NULL) { + result = initializer_from_expression(outer_type, expression); + if (result != NULL) { next_if(','); if (token.kind != '}') { - warningf(WARN_OTHER, HERE, "excessive elements in initializer for type '%T'", orig_type); + warningf(WARN_OTHER, HERE, "excessive elements in initializer for type '%T'", outer_type); } /* TODO: eat , ... */ - return sub; + goto out; } } @@ -2121,12 +2114,8 @@ finish_designator: ARR_APP1(initializer_t*, initializers, sub); error_parse_next: - if (token.kind == '}') { + if (!next_if(',')) break; - } - add_anchor_token('}'); - expect(','); - rem_anchor_token('}'); if (token.kind == '}') { break; } @@ -2144,22 +2133,19 @@ error_parse_next: size_t len = ARR_LEN(initializers); size_t size = sizeof(initializer_list_t) + len * sizeof(initializers[0]); - initializer_t *result = allocate_ast_zero(size); - result->kind = INITIALIZER_LIST; - result->list.len = len; + result = allocate_ast_zero(size); + result->kind = INITIALIZER_LIST; + result->list.len = len; memcpy(&result->list.initializers, initializers, len * sizeof(initializers[0])); - - DEL_ARR_F(initializers); - ascend_to(path, top_path_level+1); - - return result; + goto out; end_error: skip_initializers(); +out: DEL_ARR_F(initializers); ascend_to(path, top_path_level+1); - return NULL; + return result; } static expression_t *make_size_literal(size_t value) @@ -2221,9 +2207,10 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env) size = max_index + 1; break; - case INITIALIZER_STRING: - size = result->string.string.size + 1; + case INITIALIZER_STRING: { + size = get_string_len(&get_init_string(result)->value) + 1; break; + } case INITIALIZER_DESIGNATOR: case INITIALIZER_VALUE: @@ -2322,6 +2309,7 @@ static compound_t *parse_compound_type_specifier(bool is_struct) } if (attributes != NULL) { + entity->compound.attributes = attributes; handle_entity_attributes(attributes, entity); } @@ -2477,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, @@ -2669,9 +2658,9 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) = parse_microsoft_extended_decl_modifier(specifiers->attributes); break; - case T___thread: + case T__Thread_local: if (specifiers->thread_local) { - errorf(HERE, "duplicate '__thread'"); + errorf(HERE, "duplicate %K", &token); } else { specifiers->thread_local = true; check_thread_storage_class: @@ -2686,7 +2675,7 @@ check_thread_storage_class: case STORAGE_CLASS_REGISTER: wrong = "register"; goto wrong_thread_storage_class; case STORAGE_CLASS_TYPEDEF: wrong = "typedef"; goto wrong_thread_storage_class; wrong_thread_storage_class: - errorf(HERE, "'__thread' used with '%s'", wrong); + errorf(HERE, "%K used with '%s'", &token, wrong); break; } } @@ -3015,7 +3004,8 @@ warn_about_long_long: } else { errorf(pos, "multiple datatypes in declaration"); } - goto end_error; + specifiers->type = type_error_type; + return; } } @@ -3044,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) @@ -4587,8 +4573,7 @@ static void check_declarations(void) warn_unused_entity(WARN_UNUSED_PARAMETER, scope->entities, NULL); } if (is_warn_on(WARN_UNUSED_VARIABLE)) { - walk_statements(current_function->statement, check_unused_variables, - NULL); + walk_statements(current_function->body, check_unused_variables, NULL); } } @@ -4805,7 +4790,7 @@ static void check_reachable(statement_t *const stmt) return; if (is_constant_expression(expr) == EXPR_CLASS_CONSTANT) { - long const val = fold_constant_to_int(expr); + ir_tarval *const val = fold_constant_to_tarval(expr); case_label_statement_t * defaults = NULL; for (case_label_statement_t *i = switchs->first_case; i != NULL; i = i->next) { if (i->expression == NULL) { @@ -4813,7 +4798,9 @@ static void check_reachable(statement_t *const stmt) continue; } - if (i->first_case <= val && val <= i->last_case) { + if (i->first_case == val || i->last_case == val || + ((tarval_cmp(i->first_case, val) & ir_relation_less_equal) + && (tarval_cmp(val, i->last_case) & ir_relation_less_equal))) { check_reachable((statement_t*)i); return; } @@ -4858,7 +4845,6 @@ static void check_reachable(statement_t *const stmt) next = parent; switch (parent->kind) { - case STATEMENT_WHILE: goto continue_while; case STATEMENT_DO_WHILE: goto continue_do_while; case STATEMENT_FOR: goto continue_for; @@ -4874,7 +4860,6 @@ static void check_reachable(statement_t *const stmt) switch (parent->kind) { case STATEMENT_SWITCH: - case STATEMENT_WHILE: case STATEMENT_DO_WHILE: case STATEMENT_FOR: last = parent; @@ -4912,25 +4897,6 @@ found_break_parent: next = stmt->case_label.statement; break; - case STATEMENT_WHILE: { - while_statement_t const *const whiles = &stmt->whiles; - expression_t const *const cond = whiles->condition; - - if (!expression_returns(cond)) - return; - - int const val = determine_truth(cond); - - if (val >= 0) - check_reachable(whiles->body); - - if (val > 0) - return; - - next = stmt->base.next; - break; - } - case STATEMENT_DO_WHILE: next = stmt->do_while.body; break; @@ -5035,31 +5001,6 @@ found_break_parent: next = next->base.next; break; - case STATEMENT_WHILE: { -continue_while: - if (next->base.reachable) - return; - next->base.reachable = true; - - while_statement_t const *const whiles = &next->whiles; - expression_t const *const cond = whiles->condition; - - if (!expression_returns(cond)) - return; - - int const val = determine_truth(cond); - - if (val >= 0) - check_reachable(whiles->body); - - if (val > 0) - return; - - last = next; - next = next->base.next; - break; - } - case STATEMENT_DO_WHILE: { continue_do_while: if (next->base.reachable) @@ -5329,7 +5270,7 @@ static void parse_external_declaration(void) environment_push(parameter); } - if (function->statement != NULL) { + if (function->body != NULL) { parser_error_multiple_definition(entity, HERE); eat_block(); } else { @@ -5346,7 +5287,7 @@ static void parse_external_declaration(void) label_anchor = &label_first; statement_t *const body = parse_compound_statement(false); - function->statement = body; + function->body = body; first_err = true; check_labels(); check_declarations(); @@ -5481,8 +5422,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; @@ -5705,8 +5645,8 @@ static type_t *get_string_type(string_encoding_t const enc) static expression_t *parse_string_literal(void) { 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); + expr->string_literal.value = concat_string_literals(); + expr->base.type = get_string_type(expr->string_literal.value.encoding); return expr; } @@ -5724,110 +5664,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; } /** @@ -5836,13 +5870,13 @@ static expression_t *parse_number_literal(void) static expression_t *parse_character_constant(void) { expression_t *const literal = allocate_expression_zero(EXPR_LITERAL_CHARACTER); - literal->string_literal.encoding = token.string.encoding; - literal->string_literal.value = token.string.string; + literal->string_literal.value = token.literal.string; - switch (token.string.encoding) { + 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 (literal->string_literal.value.size > 1) { + if (size > 1) { if (!GNU_MODE && !(c_mode & _C99)) { errorf(HERE, "more than 1 character in character constant"); } else { @@ -5854,7 +5888,7 @@ static expression_t *parse_character_constant(void) case STRING_ENCODING_WIDE: literal->base.type = type_int; - if (wstrlen(&literal->string_literal.value) > 1) { + if (size > 1) { warningf(WARN_MULTICHAR, HERE, "multi-character character constant"); } break; @@ -5949,7 +5983,7 @@ type_t *revert_automatic_type_conversion(const expression_t *expression) } case EXPR_STRING_LITERAL: { - size_t const size = expression->string_literal.value.size + 1; + 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); } @@ -6643,8 +6677,7 @@ 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_STRING_LITERAL: return parse_string_literal(); case T___func__: return parse_function_keyword(FUNCNAME_FUNCTION); @@ -6764,7 +6797,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind) expression_t *tp_expression = allocate_expression_zero(kind); tp_expression->base.type = type_size_t; - eat(kind == EXPR_SIZEOF ? T_sizeof : T___alignof__); + eat(kind == EXPR_SIZEOF ? T_sizeof : T__Alignof); type_t *orig_type; expression_t *expression; @@ -6867,9 +6900,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'", @@ -6994,7 +7025,6 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) "third argument of '%Y' must be a constant expression", call->function->reference.entity->base.symbol); } - locality = rw->next; } break; default: @@ -8576,7 +8606,7 @@ static void init_expression_parsers(void) register_expression_parser(parse_EXPR_UNARY_PREFIX_INCREMENT, T_PLUSPLUS); register_expression_parser(parse_EXPR_UNARY_PREFIX_DECREMENT, T_MINUSMINUS); register_expression_parser(parse_sizeof, T_sizeof); - register_expression_parser(parse_alignof, T___alignof__); + register_expression_parser(parse_alignof, T__Alignof); register_expression_parser(parse_extension, T___extension__); register_expression_parser(parse_builtin_classify_type, T___builtin_classify_type); register_expression_parser(parse_delete, T_delete); @@ -8812,7 +8842,7 @@ static statement_t *parse_case_statement(void) } statement->case_label.is_bad = true; } else { - long const val = fold_constant_to_int(expression); + ir_tarval *val = fold_constant_to_tarval(expression); statement->case_label.first_case = val; statement->case_label.last_case = val; } @@ -8836,10 +8866,11 @@ static statement_t *parse_case_statement(void) } statement->case_label.is_bad = true; } else { - long const val = fold_constant_to_int(end_range); + ir_tarval *val = fold_constant_to_tarval(end_range); statement->case_label.last_case = val; - if (val < statement->case_label.first_case) { + if (tarval_cmp(val, statement->case_label.first_case) + == ir_relation_less) { statement->case_label.is_empty_range = true; warningf(WARN_OTHER, pos, "empty range specified"); } @@ -8944,6 +8975,7 @@ static statement_t *parse_label_statement(void) } else { label->base.source_position = *pos; label->statement = statement; + label->n_users += 1; } eat(':'); @@ -9043,28 +9075,32 @@ static void check_enum_cases(const switch_statement_t *statement) { if (!is_warn_on(WARN_SWITCH_ENUM)) return; - const type_t *type = skip_typeref(statement->expression->base.type); + type_t *type = skip_typeref(statement->expression->base.type); if (! is_type_enum(type)) return; - const enum_type_t *enumt = &type->enumt; + enum_type_t *enumt = &type->enumt; /* if we have a default, no warnings */ if (statement->default_label != NULL) return; + determine_enum_values(enumt); + /* FIXME: calculation of value should be done while parsing */ /* TODO: quadratic algorithm here. Change to an n log n one */ - long last_value = -1; - const entity_t *entry = enumt->enume->base.next; + const entity_t *entry = enumt->enume->base.next; for (; entry != NULL && entry->kind == ENTITY_ENUM_VALUE; entry = entry->base.next) { - const expression_t *expression = entry->enum_value.value; - long value = expression != NULL ? fold_constant_to_int(expression) : last_value + 1; - bool found = false; - for (const case_label_statement_t *l = statement->first_case; l != NULL; l = l->next) { + ir_tarval *value = entry->enum_value.tv; + bool found = false; + for (const case_label_statement_t *l = statement->first_case; l != NULL; + l = l->next) { if (l->expression == NULL) continue; - if (l->first_case <= value && value <= l->last_case) { + if (l->first_case == l->last_case && l->first_case != value) + continue; + if ((tarval_cmp(l->first_case, value) & ir_relation_less_equal) + && (tarval_cmp(value, l->last_case) & ir_relation_less_equal)) { found = true; break; } @@ -9073,7 +9109,6 @@ static void check_enum_cases(const switch_statement_t *statement) source_position_t const *const pos = &statement->base.source_position; warningf(WARN_SWITCH_ENUM, pos, "'%N' not handled in switch", entry); } - last_value = value; } } @@ -9134,20 +9169,20 @@ static statement_t *parse_loop_body(statement_t *const loop) */ static statement_t *parse_while(void) { - statement_t *statement = allocate_statement_zero(STATEMENT_WHILE); + statement_t *statement = allocate_statement_zero(STATEMENT_FOR); eat(T_while); PUSH_PARENT(statement); - PUSH_SCOPE_STATEMENT(&statement->whiles.scope); + PUSH_SCOPE_STATEMENT(&statement->fors.scope); expression_t *const cond = parse_condition(); - statement->whiles.condition = cond; + statement->fors.condition = cond; /* §6.8.5:2 The controlling expression of an iteration statement shall * have scalar type. */ semantic_condition(cond, "condition of 'while'-statement"); - statement->whiles.body = parse_loop_body(statement); + statement->fors.body = parse_loop_body(statement); POP_SCOPE(); POP_PARENT(); @@ -9280,6 +9315,7 @@ static statement_t *parse_goto(void) label_t *const label = get_label("while parsing goto"); if (label) { + label->n_users += 1; label->used = true; statement->gotos.label = label; @@ -9738,17 +9774,17 @@ 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__Alignof); add_anchor_token(T__Bool); add_anchor_token(T__Complex); add_anchor_token(T__Imaginary); + add_anchor_token(T__Thread_local); add_anchor_token(T___PRETTY_FUNCTION__); - add_anchor_token(T___alignof__); add_anchor_token(T___attribute__); add_anchor_token(T___builtin_va_start); add_anchor_token(T___extension__); @@ -9756,7 +9792,6 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) add_anchor_token(T___imag__); add_anchor_token(T___label__); add_anchor_token(T___real__); - add_anchor_token(T___thread); add_anchor_token(T_asm); add_anchor_token(T_auto); add_anchor_token(T_bool); @@ -9904,7 +9939,6 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) rem_anchor_token(T_bool); rem_anchor_token(T_auto); rem_anchor_token(T_asm); - rem_anchor_token(T___thread); rem_anchor_token(T___real__); rem_anchor_token(T___label__); rem_anchor_token(T___imag__); @@ -9912,17 +9946,17 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) rem_anchor_token(T___extension__); rem_anchor_token(T___builtin_va_start); rem_anchor_token(T___attribute__); - rem_anchor_token(T___alignof__); rem_anchor_token(T___PRETTY_FUNCTION__); + rem_anchor_token(T__Thread_local); rem_anchor_token(T__Imaginary); rem_anchor_token(T__Complex); rem_anchor_token(T__Bool); + rem_anchor_token(T__Alignof); 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('~'); @@ -9969,7 +10003,7 @@ static void check_unused_globals(void) continue; why = WARN_UNUSED_FUNCTION; - s = entity->function.statement != NULL ? "defined" : "declared"; + s = entity->function.body != NULL ? "defined" : "declared"; } else { why = WARN_UNUSED_VARIABLE; s = "defined"; @@ -10143,8 +10177,6 @@ void start_parsing(void) { environment_stack = NEW_ARR_F(stack_entry_t, 0); label_stack = NEW_ARR_F(stack_entry_t, 0); - error_count = 0; - warning_count = 0; print_to_file(stderr); @@ -10207,7 +10239,7 @@ static void complete_incomplete_arrays(void) static void prepare_main_collect2(entity_t *const entity) { - PUSH_SCOPE(&entity->function.statement->compound.scope); + PUSH_SCOPE(&entity->function.body->compound.scope); // create call to __main symbol_t *symbol = symbol_table_insert("__main"); @@ -10229,9 +10261,9 @@ static void prepare_main_collect2(entity_t *const entity) expr_statement->base.source_position = builtin_source_position; expr_statement->expression.expression = call; - statement_t *statement = entity->function.statement; - assert(statement->kind == STATEMENT_COMPOUND); - compound_statement_t *compounds = &statement->compound; + statement_t *const body = entity->function.body; + assert(body->kind == STATEMENT_COMPOUND); + compound_statement_t *compounds = &body->compound; expr_statement->base.next = compounds->statements; compounds->statements = expr_statement; @@ -10258,8 +10290,6 @@ void parse(void) */ void init_parser(void) { - sym_anonymous = symbol_table_insert(""); - memset(token_anchor_set, 0, sizeof(token_anchor_set)); init_expression_parsers();