X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=417b1e23c03325ae9d18118042d8d7cc654af47b;hb=d7d33f2a6f135d3e8c948726f97bb6d9fab3e781;hp=3a3f75d301fcab7aa2f4396e74ec6842ed40496d;hpb=a4652a9c4eb2aecc36ce8b1c261adfe82b5cb424;p=cparser diff --git a/parser.c b/parser.c index 3a3f75d..417b1e2 100644 --- a/parser.c +++ b/parser.c @@ -41,21 +41,13 @@ #include "adt/error.h" #include "adt/array.h" -/** if wchar_t is equal to unsigned short. */ -bool opt_short_wchar_t = -#ifdef _WIN32 - true; -#else - false; -#endif - //#define PRINT_TOKENS #define MAX_LOOKAHEAD 2 typedef struct { - entity_t *old_entity; - symbol_t *symbol; - namespace_t namespc; + entity_t *old_entity; + symbol_t *symbol; + entity_namespace_t namespc; } stack_entry_t; typedef struct argument_list_t argument_list_t; @@ -108,36 +100,34 @@ typedef struct parse_initializer_env_t { typedef entity_t* (*parsed_declaration_func) (entity_t *declaration, bool is_definition); /** The current token. */ -static token_t token; +static token_t token; /** The lookahead ring-buffer. */ -static token_t lookahead_buffer[MAX_LOOKAHEAD]; +static token_t lookahead_buffer[MAX_LOOKAHEAD]; /** Position of the next token in the lookahead buffer. */ -static int lookahead_bufpos; -static stack_entry_t *environment_stack = NULL; -static stack_entry_t *label_stack = NULL; -static stack_entry_t *local_label_stack = NULL; -/** The global file scope. */ -static scope_t *file_scope = NULL; -/** The current scope. */ -static scope_t *scope = NULL; +static int lookahead_bufpos; +static stack_entry_t *environment_stack = NULL; +static stack_entry_t *label_stack = NULL; +static scope_t *file_scope = NULL; +static scope_t *current_scope = NULL; /** Point to the current function declaration if inside a function. */ -static function_t *current_function = NULL; -static entity_t *current_init_decl = NULL; -static switch_statement_t *current_switch = NULL; -static statement_t *current_loop = NULL; -static statement_t *current_parent = NULL; -static ms_try_statement_t *current_try = NULL; -static goto_statement_t *goto_first = NULL; -static goto_statement_t *goto_last = NULL; -static label_statement_t *label_first = NULL; -static label_statement_t *label_last = NULL; +static function_t *current_function = NULL; +static entity_t *current_init_decl = NULL; +static switch_statement_t *current_switch = NULL; +static statement_t *current_loop = NULL; +static statement_t *current_parent = NULL; +static ms_try_statement_t *current_try = NULL; +static linkage_kind_t current_linkage = LINKAGE_INVALID; +static goto_statement_t *goto_first = NULL; +static goto_statement_t **goto_anchor = NULL; +static label_statement_t *label_first = NULL; +static label_statement_t **label_anchor = NULL; /** current translation unit. */ -static translation_unit_t *unit = NULL; +static translation_unit_t *unit = NULL; /** true if we are in a type property context (evaluation only for type. */ -static bool in_type_prop = false; +static bool in_type_prop = false; /** true in we are in a __extension__ context. */ -static bool in_gcc_extension = false; -static struct obstack temp_obst; +static bool in_gcc_extension = false; +static struct obstack temp_obst; #define PUSH_PARENT(stmt) \ @@ -185,6 +175,8 @@ static statement_t *parse_statement(void); static expression_t *parse_sub_expression(precedence_t); static expression_t *parse_expression(void); static type_t *parse_typename(void); +static void parse_externals(void); +static void parse_external(void); static void parse_compound_type_entries(compound_t *compound_declaration); static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, @@ -202,6 +194,13 @@ static void semantic_comparison(binary_expression_t *expression); case T_register: \ case T___thread: +#define STORAGE_CLASSES_NO_EXTERN \ + case T_typedef: \ + case T_static: \ + case T_auto: \ + case T_register: \ + case T___thread: + #define TYPE_QUALIFIERS \ case T_const: \ case T_restrict: \ @@ -210,33 +209,29 @@ static void semantic_comparison(binary_expression_t *expression); case T__forceinline: \ case T___attribute__: -#ifdef PROVIDE_COMPLEX #define COMPLEX_SPECIFIERS \ case T__Complex: #define IMAGINARY_SPECIFIERS \ case T__Imaginary: -#else -#define COMPLEX_SPECIFIERS -#define IMAGINARY_SPECIFIERS -#endif #define TYPE_SPECIFIERS \ - case T_void: \ + case T__Bool: \ + case T___builtin_va_list: \ + case T___typeof__: \ + case T__declspec: \ + case T_bool: \ case T_char: \ - case T_short: \ + case T_double: \ + case T_enum: \ + case T_float: \ case T_int: \ case T_long: \ - case T_float: \ - case T_double: \ + case T_short: \ case T_signed: \ - case T_unsigned: \ - case T__Bool: \ case T_struct: \ case T_union: \ - case T_enum: \ - case T___typeof__: \ - case T___builtin_va_list: \ - case T__declspec: \ + case T_unsigned: \ + case T_void: \ COMPLEX_SPECIFIERS \ IMAGINARY_SPECIFIERS @@ -245,6 +240,11 @@ static void semantic_comparison(binary_expression_t *expression); TYPE_QUALIFIERS \ TYPE_SPECIFIERS +#define DECLARATION_START_NO_EXTERN \ + STORAGE_CLASSES_NO_EXTERN \ + TYPE_QUALIFIERS \ + TYPE_SPECIFIERS + #define TYPENAME_START \ TYPE_QUALIFIERS \ TYPE_SPECIFIERS @@ -296,9 +296,11 @@ static void semantic_comparison(binary_expression_t *expression); case T___func__: \ case T___noop: \ case T__assume: \ - case T_sizeof: \ case T_delete: \ - case T_throw: + case T_false: \ + case T_sizeof: \ + case T_throw: \ + case T_true: /** * Allocate an AST node with given size and @@ -323,9 +325,10 @@ static size_t get_entity_struct_size(entity_kind_t kind) [ENTITY_ENUM] = sizeof(enum_t), [ENTITY_ENUM_VALUE] = sizeof(enum_value_t), [ENTITY_LABEL] = sizeof(label_t), - [ENTITY_LOCAL_LABEL] = sizeof(label_t) + [ENTITY_LOCAL_LABEL] = sizeof(label_t), + [ENTITY_NAMESPACE] = sizeof(namespace_t) }; - assert(kind <= sizeof(sizes) / sizeof(sizes[0])); + assert(kind < sizeof(sizes) / sizeof(sizes[0])); assert(sizes[kind] != 0); return sizes[kind]; } @@ -367,7 +370,7 @@ static size_t get_statement_struct_size(statement_kind_t kind) [STATEMENT_MS_TRY] = sizeof(ms_try_statement_t), [STATEMENT_LEAVE] = sizeof(leave_statement_t) }; - assert(kind <= sizeof(sizes) / sizeof(sizes[0])); + assert(kind < sizeof(sizes) / sizeof(sizes[0])); assert(sizes[kind] != 0); return sizes[kind]; } @@ -414,7 +417,7 @@ static size_t get_expression_struct_size(expression_kind_t kind) if (kind >= EXPR_BINARY_FIRST && kind <= EXPR_BINARY_LAST) { return sizes[EXPR_BINARY_FIRST]; } - assert(kind <= sizeof(sizes) / sizeof(sizes[0])); + assert(kind < sizeof(sizes) / sizeof(sizes[0])); assert(sizes[kind] != 0); return sizes[kind]; } @@ -443,8 +446,9 @@ static expression_t *allocate_expression_zero(expression_kind_t kind) size_t size = get_expression_struct_size(kind); expression_t *res = allocate_ast_zero(size); - res->base.kind = kind; - res->base.type = type_error_type; + res->base.kind = kind; + res->base.type = type_error_type; + res->base.source_position = token.source_position; return res; } @@ -453,9 +457,7 @@ static expression_t *allocate_expression_zero(expression_kind_t kind) */ static expression_t *create_invalid_expression(void) { - expression_t *expression = allocate_expression_zero(EXPR_INVALID); - expression->base.source_position = token.source_position; - return expression; + return allocate_expression_zero(EXPR_INVALID); } /** @@ -573,14 +575,6 @@ static size_t label_top(void) return ARR_LEN(label_stack); } -/** - * Returns the index of the top element of the local label stack. - */ -static size_t local_label_top(void) -{ - return ARR_LEN(local_label_stack); -} - /** * Return the next token. */ @@ -721,7 +715,7 @@ static void eat_block(void) next_token(); } -#define eat(token_type) do { assert(token.type == token_type); next_token(); } while (0) +#define eat(token_type) do { assert(token.type == (token_type)); next_token(); } while (0) /** * Report a parse error because an expected token was not found. @@ -781,22 +775,23 @@ static void type_error_incompatible(const char *msg, static void scope_push(scope_t *new_scope) { - if (scope != NULL) { - new_scope->depth = scope->depth + 1; + if (current_scope != NULL) { + new_scope->depth = current_scope->depth + 1; } - new_scope->parent = scope; - scope = new_scope; + new_scope->parent = current_scope; + current_scope = new_scope; } static void scope_pop(void) { - scope = scope->parent; + current_scope = current_scope->parent; } /** * Search an entity by its symbol in a given namespace. */ -static entity_t *get_entity(const symbol_t *const symbol, namespace_t namespc) +static entity_t *get_entity(const symbol_t *const symbol, + namespace_tag_t namespc) { entity_t *entity = symbol->entity; for( ; entity != NULL; entity = entity->base.symbol_next) { @@ -813,8 +808,8 @@ static entity_t *get_entity(const symbol_t *const symbol, namespace_t namespc) */ static void stack_push(stack_entry_t **stack_ptr, entity_t *entity) { - symbol_t *symbol = entity->base.symbol; - namespace_t namespc = entity->base.namespc; + symbol_t *symbol = entity->base.symbol; + entity_namespace_t namespc = entity->base.namespc; assert(namespc != NAMESPACE_INVALID); /* replace/add entity into entity list of the symbol */ @@ -863,18 +858,6 @@ static void label_push(entity_t *label) stack_push(&label_stack, label); } -/** - * Push a declaration of the local label stack. - * - * @param declaration the declaration - */ -static void local_label_push(entity_t *label) -{ - assert(label->base.parent_scope != NULL); - label->base.parent_scope = scope; - stack_push(&local_label_stack, label); -} - /** * pops symbols from the environment stack until @p new_top is the top element */ @@ -891,9 +874,9 @@ static void stack_pop_to(stack_entry_t **stack_ptr, size_t new_top) for(i = top; i > new_top; --i) { stack_entry_t *entry = &stack[i - 1]; - entity_t *old_entity = entry->old_entity; - symbol_t *symbol = entry->symbol; - namespace_t namespc = entry->namespc; + entity_t *old_entity = entry->old_entity; + symbol_t *symbol = entry->symbol; + entity_namespace_t namespc = entry->namespc; /* replace with old_entity/remove */ entity_t **anchor; @@ -941,18 +924,6 @@ static void label_pop_to(size_t new_top) stack_pop_to(&label_stack, new_top); } -/** - * Pop all entries from the local label stack until the new_top - * is reached. - * - * @param new_top the new stack top - */ -static void local_label_pop_to(size_t new_top) -{ - stack_pop_to(&local_label_stack, new_top); -} - - static int get_akind_rank(atomic_type_kind_t akind) { return (int) akind; @@ -1194,25 +1165,6 @@ static expression_t *parse_assignment_expression(void) return parse_sub_expression(PREC_ASSIGNMENT); } -static type_t *make_global_typedef(const char *name, type_t *type) -{ - symbol_t *const symbol = symbol_table_insert(name); - - entity_t *const entity = allocate_entity_zero(ENTITY_TYPEDEF); - entity->base.symbol = symbol; - entity->base.source_position = builtin_source_position; - entity->base.namespc = NAMESPACE_NORMAL; - entity->typedefe.type = type; - entity->typedefe.builtin = true; - - record_entity(entity, false); - - type_t *typedef_type = allocate_type_zero(TYPE_TYPEDEF); - typedef_type->typedeft.typedefe = &entity->typedefe; - - return typedef_type; -} - static string_t parse_string_literals(void) { assert(token.type == T_STRING_LITERAL); @@ -3004,13 +2956,13 @@ static compound_t *parse_compound_type_specifier(bool is_struct) symbol = token.v.symbol; next_token(); - namespace_t const namespc = + namespace_tag_t const namespc = is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION; entity_t *entity = get_entity(symbol, namespc); if (entity != NULL) { assert(entity->kind == (is_struct ? ENTITY_STRUCT : ENTITY_UNION)); compound = &entity->compound; - if (compound->base.parent_scope != scope && + if (compound->base.parent_scope != current_scope && (token.type == '{' || token.type == ';')) { /* we're in an inner scope and have a definition. Override existing definition in outer scope */ @@ -3045,11 +2997,11 @@ static compound_t *parse_compound_type_specifier(bool is_struct) (is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION); compound->base.source_position = token.source_position; compound->base.symbol = symbol; - compound->base.parent_scope = scope; + compound->base.parent_scope = current_scope; if (symbol != NULL) { environment_push(entity); } - append_entity(scope, entity); + append_entity(current_scope, entity); } if (token.type == '{') { @@ -3139,7 +3091,7 @@ static type_t *parse_enum_specifier(void) entity->base.namespc = NAMESPACE_ENUM; entity->base.source_position = token.source_position; entity->base.symbol = symbol; - entity->base.parent_scope = scope; + entity->base.parent_scope = current_scope; } type_t *const type = allocate_type_zero(TYPE_ENUM); @@ -3153,7 +3105,7 @@ static type_t *parse_enum_specifier(void) if (symbol != NULL) { environment_push(entity); } - append_entity(scope, entity); + append_entity(current_scope, entity); entity->enume.complete = true; parse_enum_entries(type); @@ -3445,6 +3397,8 @@ static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind) if (is_declaration(entity)) { entity->declaration.type = type_error_type; entity->declaration.implicit = true; + } else if (kind == ENTITY_TYPEDEF) { + entity->typedefe.type = type_error_type; } record_entity(entity, false); return entity; @@ -3638,30 +3592,31 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) /* type specifiers */ #define MATCH_SPECIFIER(token, specifier, name) \ case token: \ - next_token(); \ if (type_specifiers & specifier) { \ errorf(HERE, "multiple " name " type specifiers given"); \ } else { \ type_specifiers |= specifier; \ } \ + next_token(); \ break - MATCH_SPECIFIER(T_void, SPECIFIER_VOID, "void"); - MATCH_SPECIFIER(T_char, SPECIFIER_CHAR, "char"); - MATCH_SPECIFIER(T_short, SPECIFIER_SHORT, "short"); - MATCH_SPECIFIER(T_int, SPECIFIER_INT, "int"); - MATCH_SPECIFIER(T_float, SPECIFIER_FLOAT, "float"); - MATCH_SPECIFIER(T_double, SPECIFIER_DOUBLE, "double"); - MATCH_SPECIFIER(T_signed, SPECIFIER_SIGNED, "signed"); - MATCH_SPECIFIER(T_unsigned, SPECIFIER_UNSIGNED, "unsigned"); MATCH_SPECIFIER(T__Bool, SPECIFIER_BOOL, "_Bool"); - MATCH_SPECIFIER(T__int8, SPECIFIER_INT8, "_int8"); + MATCH_SPECIFIER(T__Complex, SPECIFIER_COMPLEX, "_Complex"); + MATCH_SPECIFIER(T__Imaginary, SPECIFIER_IMAGINARY, "_Imaginary"); + MATCH_SPECIFIER(T__int128, SPECIFIER_INT128, "_int128"); MATCH_SPECIFIER(T__int16, SPECIFIER_INT16, "_int16"); MATCH_SPECIFIER(T__int32, SPECIFIER_INT32, "_int32"); MATCH_SPECIFIER(T__int64, SPECIFIER_INT64, "_int64"); - MATCH_SPECIFIER(T__int128, SPECIFIER_INT128, "_int128"); - MATCH_SPECIFIER(T__Complex, SPECIFIER_COMPLEX, "_Complex"); - MATCH_SPECIFIER(T__Imaginary, SPECIFIER_IMAGINARY, "_Imaginary"); + MATCH_SPECIFIER(T__int8, SPECIFIER_INT8, "_int8"); + MATCH_SPECIFIER(T_bool, SPECIFIER_BOOL, "bool"); + MATCH_SPECIFIER(T_char, SPECIFIER_CHAR, "char"); + MATCH_SPECIFIER(T_double, SPECIFIER_DOUBLE, "double"); + MATCH_SPECIFIER(T_float, SPECIFIER_FLOAT, "float"); + MATCH_SPECIFIER(T_int, SPECIFIER_INT, "int"); + MATCH_SPECIFIER(T_short, SPECIFIER_SHORT, "short"); + MATCH_SPECIFIER(T_signed, SPECIFIER_SIGNED, "signed"); + MATCH_SPECIFIER(T_unsigned, SPECIFIER_UNSIGNED, "unsigned"); + MATCH_SPECIFIER(T_void, SPECIFIER_VOID, "void"); case T__forceinline: /* only in microsoft mode */ @@ -3674,7 +3629,6 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) break; case T_long: - next_token(); if (type_specifiers & SPECIFIER_LONG_LONG) { errorf(HERE, "multiple type specifiers given"); } else if (type_specifiers & SPECIFIER_LONG) { @@ -3682,6 +3636,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) } else { type_specifiers |= SPECIFIER_LONG; } + next_token(); break; case T_struct: { @@ -4250,6 +4205,8 @@ static construct_type_t *parse_function_declarator(scope_t *scope) { type_t *type = allocate_type_zero(TYPE_FUNCTION); + type->function.linkage = current_linkage; + /* TODO: revive this... once we know exactly how to do it */ #if 0 decl_modifiers_t modifiers = entity->declaration.modifiers; @@ -4636,7 +4593,8 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, storage_class_t storage_class = specifiers->storage_class; entity->declaration.declared_storage_class = storage_class; - if (storage_class == STORAGE_CLASS_NONE && scope != file_scope) { + if (storage_class == STORAGE_CLASS_NONE + && current_scope != file_scope) { storage_class = STORAGE_CLASS_AUTO; } entity->declaration.storage_class = storage_class; @@ -4728,6 +4686,34 @@ static bool is_sym_main(const symbol_t *const sym) return strcmp(sym->string, "main") == 0; } +static const char *get_entity_kind_name(entity_kind_t kind) +{ + switch ((entity_kind_tag_t) kind) { + case ENTITY_FUNCTION: return "function"; + case ENTITY_VARIABLE: return "variable"; + case ENTITY_COMPOUND_MEMBER: return "compound type member"; + case ENTITY_STRUCT: return "struct"; + case ENTITY_UNION: return "union"; + case ENTITY_ENUM: return "enum"; + case ENTITY_ENUM_VALUE: return "enum value"; + case ENTITY_LABEL: return "label"; + case ENTITY_LOCAL_LABEL: return "local label"; + case ENTITY_TYPEDEF: return "typedef"; + case ENTITY_NAMESPACE: return "namespace"; + case ENTITY_INVALID: break; + } + + panic("Invalid entity kind encountered in get_entity_kind_name"); +} + +static void error_redefined_as_different_kind(const source_position_t *pos, + const entity_t *old, entity_kind_t new_kind) +{ + errorf(pos, "redeclaration of %s '%Y' as %s (declared %P)", + get_entity_kind_name(old->kind), old->base.symbol, + get_entity_kind_name(new_kind), &old->base.source_position); +} + /** * record entities for the NAMESPACE_NORMAL, and produce error messages/warnings * for various problems that occur for multiple definitions @@ -4735,7 +4721,7 @@ static bool is_sym_main(const symbol_t *const sym) static entity_t *record_entity(entity_t *entity, const bool is_definition) { const symbol_t *const symbol = entity->base.symbol; - const namespace_t namespc = entity->base.namespc; + const namespace_tag_t namespc = (namespace_tag_t)entity->base.namespc; const source_position_t *pos = &entity->base.source_position; assert(symbol != NULL); @@ -4755,7 +4741,8 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition) orig_type, symbol); } - if (warning.main && scope == file_scope && is_sym_main(symbol)) { + if (warning.main && current_scope == file_scope + && is_sym_main(symbol)) { check_type_of_main(entity); } } @@ -4763,7 +4750,7 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition) if (is_declaration(entity)) { if (warning.nested_externs && entity->declaration.storage_class == STORAGE_CLASS_EXTERN - && scope != file_scope) { + && current_scope != file_scope) { warningf(pos, "nested extern declaration of '%#T'", entity->declaration.type, symbol); } @@ -4771,7 +4758,7 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition) if (previous_entity != NULL && previous_entity->base.parent_scope == ¤t_function->parameters - && scope->depth == previous_entity->base.parent_scope->depth + 1) { + && current_scope->depth == previous_entity->base.parent_scope->depth+1){ assert(previous_entity->kind == ENTITY_VARIABLE); errorf(pos, @@ -4783,12 +4770,11 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition) } if (previous_entity != NULL - && previous_entity->base.parent_scope == scope) { + && previous_entity->base.parent_scope == current_scope) { if (previous_entity->kind != entity->kind) { - errorf(pos, - "redeclaration of '%Y' as different kind of symbol (declared %P)", - symbol, &previous_entity->base.source_position); + error_redefined_as_different_kind(pos, previous_entity, + entity->kind); goto finish; } if (previous_entity->kind == ENTITY_ENUM_VALUE) { @@ -4945,7 +4931,7 @@ error_redeclaration: } } else if (warning.missing_declarations && entity->kind == ENTITY_VARIABLE - && scope == file_scope) { + && current_scope == file_scope) { declaration_t *declaration = &entity->declaration; if (declaration->storage_class == STORAGE_CLASS_NONE || declaration->storage_class == STORAGE_CLASS_THREAD) { @@ -4956,12 +4942,12 @@ error_redeclaration: finish: assert(entity->base.parent_scope == NULL); - assert(scope != NULL); + assert(current_scope != NULL); - entity->base.parent_scope = scope; + entity->base.parent_scope = current_scope; entity->base.namespc = NAMESPACE_NORMAL; environment_push(entity); - append_entity(scope, entity); + append_entity(current_scope, entity); return entity; } @@ -5110,7 +5096,7 @@ static entity_t *finished_kr_declaration(entity_t *entity, bool is_definition) assert(entity->base.namespc == NAMESPACE_NORMAL); entity_t *previous_entity = get_entity(symbol, NAMESPACE_NORMAL); if (previous_entity == NULL - || previous_entity->base.parent_scope != scope) { + || previous_entity->base.parent_scope != current_scope) { errorf(HERE, "expected declaration of a function parameter, found '%Y'", symbol); return entity; @@ -5174,7 +5160,7 @@ static void parse_kr_declaration_list(entity_t *entity) entity_t *parameter = entity->function.parameters.entities; for ( ; parameter != NULL; parameter = parameter->base.next) { assert(parameter->base.parent_scope == NULL); - parameter->base.parent_scope = scope; + parameter->base.parent_scope = current_scope; environment_push(parameter); } @@ -5184,7 +5170,7 @@ static void parse_kr_declaration_list(entity_t *entity) } /* pop function parameters */ - assert(scope == &entity->function.parameters); + assert(current_scope == &entity->function.parameters); scope_pop(); environment_pop_to(top); @@ -5286,8 +5272,8 @@ static void check_labels(void) "label '%Y' used but not defined", label->base.symbol); } } - goto_first = NULL; - goto_last = NULL; + goto_first = NULL; + goto_anchor = &goto_first; if (warning.unused_label) { for (const label_statement_t *label_statement = label_first; @@ -5302,7 +5288,8 @@ static void check_labels(void) } } } - label_first = label_last = NULL; + label_first = NULL; + label_anchor = &label_first; } static void warn_unused_decl(entity_t *entity, entity_t *end, @@ -5903,11 +5890,9 @@ static void parse_external_declaration(void) } assert(is_declaration(ndeclaration)); - type_t *type = ndeclaration->declaration.type; + type_t *type = skip_typeref(ndeclaration->declaration.type); - /* note that we don't skip typerefs: the standard doesn't allow them here - * (so we can't use is_type_function here) */ - if (type->kind != TYPE_FUNCTION) { + if (!is_type_function(type)) { if (is_type_valid(type)) { errorf(HERE, "declarator '%#T' has a body but is not a function type", type, ndeclaration->base.symbol); @@ -5963,11 +5948,11 @@ static void parse_external_declaration(void) entity_t *parameter = function->parameters.entities; for( ; parameter != NULL; parameter = parameter->base.next) { if (parameter->base.parent_scope == &ndeclaration->function.parameters) { - parameter->base.parent_scope = scope; + parameter->base.parent_scope = current_scope; } assert(parameter->base.parent_scope == NULL - || parameter->base.parent_scope == scope); - parameter->base.parent_scope = scope; + || parameter->base.parent_scope == current_scope); + parameter->base.parent_scope = current_scope; if (parameter->base.symbol == NULL) { errorf(¶meter->base.source_position, "parameter name omitted"); continue; @@ -6013,7 +5998,7 @@ static void parse_external_declaration(void) label_pop_to(label_stack_top); } - assert(scope == &function->parameters); + assert(current_scope == &function->parameters); scope_pop(); environment_pop_to(top); } @@ -6290,15 +6275,28 @@ static expression_t *parse_string_const(void) } } +/** + * Parse a boolean constant. + */ +static expression_t *parse_bool_const(bool value) +{ + expression_t *cnst = allocate_expression_zero(EXPR_CONST); + cnst->base.type = type_bool; + cnst->conste.v.int_value = value; + + next_token(); + + return cnst; +} + /** * Parse an integer constant. */ static expression_t *parse_int_const(void) { - expression_t *cnst = allocate_expression_zero(EXPR_CONST); - cnst->base.source_position = *HERE; - cnst->base.type = token.datatype; - cnst->conste.v.int_value = token.v.intvalue; + expression_t *cnst = allocate_expression_zero(EXPR_CONST); + cnst->base.type = token.datatype; + cnst->conste.v.int_value = token.v.intvalue; next_token(); @@ -6311,10 +6309,8 @@ static expression_t *parse_int_const(void) static expression_t *parse_character_constant(void) { expression_t *cnst = allocate_expression_zero(EXPR_CHARACTER_CONSTANT); - - cnst->base.source_position = *HERE; - cnst->base.type = token.datatype; - cnst->conste.v.character = token.v.string; + cnst->base.type = token.datatype; + cnst->conste.v.character = token.v.string; if (cnst->conste.v.character.size != 1) { if (warning.multichar && GNU_MODE) { @@ -6334,8 +6330,6 @@ static expression_t *parse_character_constant(void) static expression_t *parse_wide_character_constant(void) { expression_t *cnst = allocate_expression_zero(EXPR_WIDE_CHARACTER_CONSTANT); - - cnst->base.source_position = *HERE; cnst->base.type = token.datatype; cnst->conste.v.wide_character = token.v.wide_string; @@ -6610,6 +6604,11 @@ static expression_t *parse_reference(void) orig_type = entity->declaration.type; } else if (entity->kind == ENTITY_ENUM_VALUE) { orig_type = entity->enum_value.enum_type; + } else if (entity->kind == ENTITY_TYPEDEF) { + errorf(HERE, "encountered typedef name '%Y' while parsing expression", + symbol); + next_token(); + return create_invalid_expression(); } else { panic("expected declaration or enum value in reference"); } @@ -6746,7 +6745,7 @@ static expression_t *parse_cast(void) source_position_t source_position = token.source_position; - type_t *type = parse_typename(); + type_t *type = parse_typename(); rem_anchor_token(')'); expect(')'); @@ -6780,9 +6779,8 @@ static expression_t *parse_statement_expression(void) expression_t *expression = allocate_expression_zero(EXPR_STATEMENT); - statement_t *statement = parse_compound_statement(true); - expression->statement.statement = statement; - expression->base.source_position = statement->base.source_position; + statement_t *statement = parse_compound_statement(true); + expression->statement.statement = statement; /* find last statement and use its type */ type_t *type = type_void; @@ -6838,7 +6836,6 @@ end_error: static expression_t *parse_function_keyword(void) { - next_token(); /* TODO */ if (current_function == NULL) { @@ -6849,13 +6846,13 @@ static expression_t *parse_function_keyword(void) expression->base.type = type_char_ptr; expression->funcname.kind = FUNCNAME_FUNCTION; + next_token(); + return expression; } static expression_t *parse_pretty_function_keyword(void) { - eat(T___PRETTY_FUNCTION__); - if (current_function == NULL) { errorf(HERE, "'__PRETTY_FUNCTION__' used outside of a function"); } @@ -6864,13 +6861,13 @@ static expression_t *parse_pretty_function_keyword(void) 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) { - eat(T___FUNCSIG__); - if (current_function == NULL) { errorf(HERE, "'__FUNCSIG__' used outside of a function"); } @@ -6879,13 +6876,13 @@ static expression_t *parse_funcsig_keyword(void) expression->base.type = type_char_ptr; expression->funcname.kind = FUNCNAME_FUNCSIG; + eat(T___FUNCSIG__); + return expression; } static expression_t *parse_funcdname_keyword(void) { - eat(T___FUNCDNAME__); - if (current_function == NULL) { errorf(HERE, "'__FUNCDNAME__' used outside of a function"); } @@ -6894,6 +6891,8 @@ static expression_t *parse_funcdname_keyword(void) expression->base.type = type_char_ptr; expression->funcname.kind = FUNCNAME_FUNCDNAME; + eat(T___FUNCDNAME__); + return expression; } @@ -6957,11 +6956,11 @@ end_error: */ static expression_t *parse_offsetof(void) { - eat(T___builtin_offsetof); - expression_t *expression = allocate_expression_zero(EXPR_OFFSETOF); expression->base.type = type_size_t; + eat(T___builtin_offsetof); + expect('('); add_anchor_token(','); type_t *type = parse_typename(); @@ -6998,10 +6997,10 @@ end_error: */ static expression_t *parse_va_start(void) { - eat(T___builtin_va_start); - expression_t *expression = allocate_expression_zero(EXPR_VA_START); + eat(T___builtin_va_start); + expect('('); add_anchor_token(','); expression->va_starte.ap = parse_assignment_expression(); @@ -7031,10 +7030,10 @@ end_error: */ static expression_t *parse_va_arg(void) { - eat(T___builtin_va_arg); - expression_t *expression = allocate_expression_zero(EXPR_VA_ARG); + eat(T___builtin_va_arg); + expect('('); expression->va_arge.ap = parse_assignment_expression(); expect(','); @@ -7067,10 +7066,10 @@ static expression_t *parse_builtin_symbol(void) */ static expression_t *parse_builtin_constant(void) { - eat(T___builtin_constant_p); - expression_t *expression = allocate_expression_zero(EXPR_BUILTIN_CONSTANT_P); + eat(T___builtin_constant_p); + expect('('); add_anchor_token(')'); expression->builtin_constant.value = parse_assignment_expression(); @@ -7088,10 +7087,10 @@ end_error: */ static expression_t *parse_builtin_prefetch(void) { - eat(T___builtin_prefetch); - expression_t *expression = allocate_expression_zero(EXPR_BUILTIN_PREFETCH); + eat(T___builtin_prefetch); + expect('('); add_anchor_token(')'); expression->builtin_prefetch.adr = parse_assignment_expression(); @@ -7175,11 +7174,11 @@ end_error: */ static expression_t *parse_builtin_expect(void) { - eat(T___builtin_expect); - expression_t *expression = allocate_expression_zero(EXPR_BINARY_BUILTIN_EXPECT); + eat(T___builtin_expect); + expect('('); expression->binary.left = parse_assignment_expression(); expect(','); @@ -7199,10 +7198,9 @@ end_error: */ static expression_t *parse_assume(void) { - eat(T__assume); + expression_t *expression = allocate_expression_zero(EXPR_UNARY_ASSUME); - expression_t *expression - = allocate_expression_zero(EXPR_UNARY_ASSUME); + eat(T__assume); expect('('); add_anchor_token(')'); @@ -7226,11 +7224,11 @@ static label_t *get_label(symbol_t *symbol) entity_t *label; assert(current_function != NULL); - label = get_entity(symbol, NAMESPACE_LOCAL_LABEL); + label = get_entity(symbol, NAMESPACE_LABEL); /* if we found a local label, we already created the declaration */ if (label != NULL && label->kind == ENTITY_LOCAL_LABEL) { - if (label->base.parent_scope != scope) { - assert(label->base.parent_scope->depth < scope->depth); + if (label->base.parent_scope != current_scope) { + assert(label->base.parent_scope->depth < current_scope->depth); current_function->goto_to_outer = true; } return &label->label; @@ -7288,7 +7286,12 @@ end_error: */ static expression_t *parse_noop_expression(void) { - source_position_t source_position = *HERE; + /* the result is a (int)0 */ + expression_t *cnst = allocate_expression_zero(EXPR_CONST); + cnst->base.type = type_int; + cnst->conste.v.int_value = 0; + cnst->conste.is_ms_noop = true; + eat(T___noop); if (token.type == '(') { @@ -7310,17 +7313,8 @@ static expression_t *parse_noop_expression(void) rem_anchor_token(')'); expect(')'); - /* the result is a (int)0 */ - expression_t *cnst = allocate_expression_zero(EXPR_CONST); - cnst->base.source_position = source_position; - cnst->base.type = type_int; - cnst->conste.v.int_value = 0; - cnst->conste.is_ms_noop = true; - - return cnst; - end_error: - return create_invalid_expression(); + return cnst; } /** @@ -7329,6 +7323,8 @@ end_error: static expression_t *parse_primary_expression(void) { switch (token.type) { + case T_false: return parse_bool_const(false); + case T_true: return parse_bool_const(true); case T_INTEGER: return parse_int_const(); case T_CHARACTER_CONSTANT: return parse_character_constant(); case T_WIDE_CHARACTER_CONSTANT: return parse_wide_character_constant(); @@ -7393,22 +7389,21 @@ static void check_for_char_index_type(const expression_t *expression) static expression_t *parse_array_expression(expression_t *left) { + expression_t *expression = allocate_expression_zero(EXPR_ARRAY_ACCESS); + eat('['); add_anchor_token(']'); expression_t *inside = parse_expression(); - expression_t *expression = allocate_expression_zero(EXPR_ARRAY_ACCESS); - - array_access_expression_t *array_access = &expression->array_access; - type_t *const orig_type_left = left->base.type; type_t *const orig_type_inside = inside->base.type; type_t *const type_left = skip_typeref(orig_type_left); type_t *const type_inside = skip_typeref(orig_type_inside); - type_t *return_type; + type_t *return_type; + array_access_expression_t *array_access = &expression->array_access; if (is_type_pointer(type_left)) { return_type = type_left->pointer.points_to; array_access->array_ref = left; @@ -7434,20 +7429,17 @@ static expression_t *parse_array_expression(expression_t *left) expression->base.type = automatic_type_conversion(return_type); rem_anchor_token(']'); - if (token.type == ']') { - next_token(); - } else { - parse_error_expected("Problem while parsing array access", ']', NULL); - } + expect(']'); +end_error: return expression; } -static expression_t *parse_typeprop(expression_kind_t const kind, - source_position_t const pos) +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; - tp_expression->base.source_position = pos; + tp_expression->base.type = type_size_t; + + eat(kind == EXPR_SIZEOF ? T_sizeof : T___alignof__); char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof"; @@ -7488,7 +7480,8 @@ typeprop_expression: type->kind == TYPE_BITFIELD ? "bitfield" : NULL; if (wrong_type != NULL) { - errorf(&pos, "operand of %s expression must not be of %s type '%T'", + errorf(&tp_expression->base.source_position, + "operand of %s expression must not be of %s type '%T'", what, wrong_type, orig_type); } @@ -7499,28 +7492,23 @@ end_error: static expression_t *parse_sizeof(void) { - source_position_t pos = *HERE; - eat(T_sizeof); - return parse_typeprop(EXPR_SIZEOF, pos); + return parse_typeprop(EXPR_SIZEOF); } static expression_t *parse_alignof(void) { - source_position_t pos = *HERE; - eat(T___alignof__); - return parse_typeprop(EXPR_ALIGNOF, pos); + return parse_typeprop(EXPR_ALIGNOF); } static expression_t *parse_select_expression(expression_t *compound) { - assert(token.type == '.' || token.type == T_MINUSGREATER); + expression_t *select = allocate_expression_zero(EXPR_SELECT); + select->select.compound = compound; + assert(token.type == '.' || token.type == T_MINUSGREATER); bool is_pointer = (token.type == T_MINUSGREATER); next_token(); - expression_t *select = allocate_expression_zero(EXPR_SELECT); - select->select.compound = compound; - if (token.type != T_IDENTIFIER) { parse_error_expected("while parsing select", T_IDENTIFIER, NULL); return select; @@ -7660,11 +7648,9 @@ static void check_call_argument(const function_parameter_t *parameter, */ static expression_t *parse_call_expression(expression_t *expression) { - expression_t *result = allocate_expression_zero(EXPR_CALL); - result->base.source_position = expression->base.source_position; - - call_expression_t *call = &result->call; - call->function = expression; + expression_t *result = allocate_expression_zero(EXPR_CALL); + call_expression_t *call = &result->call; + call->function = expression; type_t *const orig_type = expression->base.type; type_t *const type = skip_typeref(orig_type); @@ -7761,6 +7747,48 @@ static bool same_compound_type(const type_t *type1, const type_t *type2) type1->compound.compound == type2->compound.compound; } +static expression_t const *get_reference_address(expression_t const *expr) +{ + bool regular_take_address = true; + for (;;) { + if (expr->kind == EXPR_UNARY_TAKE_ADDRESS) { + expr = expr->unary.value; + } else { + regular_take_address = false; + } + + if (expr->kind != EXPR_UNARY_DEREFERENCE) + break; + + expr = expr->unary.value; + } + + if (expr->kind != EXPR_REFERENCE) + return NULL; + + /* special case for functions which are automatically converted to a + * pointer to function without an extra TAKE_ADDRESS operation */ + if (!regular_take_address && + expr->reference.entity->kind != ENTITY_FUNCTION) { + return NULL; + } + + return expr; +} + +static void warn_reference_address_as_bool(expression_t const* expr) +{ + if (!warning.address) + return; + + expr = get_reference_address(expr); + if (expr != NULL) { + warningf(&expr->base.source_position, + "the address of '%Y' will always evaluate as 'true'", + expr->reference.entity->base.symbol); + } +} + /** * Parse a conditional expression, ie. 'expression ? ... : ...'. * @@ -7771,8 +7799,9 @@ static expression_t *parse_conditional_expression(expression_t *expression) expression_t *result = allocate_expression_zero(EXPR_CONDITIONAL); conditional_expression_t *conditional = &result->conditional; - conditional->base.source_position = *HERE; - conditional->condition = expression; + conditional->condition = expression; + + warn_reference_address_as_bool(expression); eat('?'); add_anchor_token(':'); @@ -7925,11 +7954,11 @@ static expression_t *parse_extension(void) */ static expression_t *parse_builtin_classify_type(void) { - eat(T___builtin_classify_type); - expression_t *result = allocate_expression_zero(EXPR_CLASSIFY_TYPE); result->base.type = type_int; + eat(T___builtin_classify_type); + expect('('); add_anchor_token(')'); expression_t *expression = parse_expression(); @@ -7949,8 +7978,7 @@ end_error: static expression_t *parse_delete(void) { expression_t *const result = allocate_expression_zero(EXPR_UNARY_DELETE); - result->base.source_position = *HERE; - result->base.type = type_void; + result->base.type = type_void; eat(T_delete); @@ -7984,8 +8012,7 @@ end_error:; static expression_t *parse_throw(void) { expression_t *const result = allocate_expression_zero(EXPR_UNARY_THROW); - result->base.source_position = *HERE; - result->base.type = type_void; + result->base.type = type_void; eat(T_throw); @@ -8114,45 +8141,6 @@ static void semantic_unexpr_plus(unary_expression_t *expression) "traditional C rejects the unary plus operator"); } -static expression_t const *get_reference_address(expression_t const *expr) -{ - bool regular_take_address = true; - for (;;) { - if (expr->kind == EXPR_UNARY_TAKE_ADDRESS) { - expr = expr->unary.value; - } else { - regular_take_address = false; - } - - if (expr->kind != EXPR_UNARY_DEREFERENCE) - break; - - expr = expr->unary.value; - } - - /* special case for functions which are automatically converted to a - * pointer to function without an extra TAKE_ADDRESS operation */ - if (!regular_take_address && expr->kind == EXPR_REFERENCE - && expr->reference.entity->kind == ENTITY_FUNCTION) { - return expr; - } - - return NULL; -} - -static void warn_function_address_as_bool(expression_t const* expr) -{ - if (!warning.address) - return; - - expr = get_reference_address(expr); - if (expr != NULL) { - warningf(&expr->base.source_position, - "the address of '%Y' will always evaluate as 'true'", - expr->reference.entity->base.symbol); - } -} - static void semantic_not(unary_expression_t *expression) { type_t *const orig_type = expression->value->base.type; @@ -8162,9 +8150,9 @@ static void semantic_not(unary_expression_t *expression) "operand of ! must be of scalar type"); } - warn_function_address_as_bool(expression->value); + warn_reference_address_as_bool(expression->value); - expression->base.type = type_int; + expression->base.type = c_mode & _CXX ? type_bool : type_int; } static void semantic_unexpr_integer(unary_expression_t *expression) @@ -8239,11 +8227,8 @@ static void semantic_take_addr(unary_expression_t *expression) return; /* §6.5.3.2 */ - if (value->kind != EXPR_ARRAY_ACCESS - && value->kind != EXPR_UNARY_DEREFERENCE - && !is_lvalue(value)) { - errorf(&expression->base.source_position, - "'&' requires an lvalue"); + if (!is_lvalue(value)) { + errorf(&expression->base.source_position, "'&' requires an lvalue"); } if (type->kind == TYPE_BITFIELD) { errorf(&expression->base.source_position, @@ -8261,7 +8246,6 @@ static expression_t *parse_##unexpression_type(void) \ { \ expression_t *unary_expression \ = allocate_expression_zero(unexpression_type); \ - unary_expression->base.source_position = *HERE; \ eat(token_type); \ unary_expression->unary.value = parse_sub_expression(PREC_UNARY); \ \ @@ -8293,9 +8277,8 @@ static expression_t *parse_##unexpression_type(expression_t *left) \ { \ expression_t *unary_expression \ = allocate_expression_zero(unexpression_type); \ - unary_expression->base.source_position = *HERE; \ eat(token_type); \ - unary_expression->unary.value = left; \ + unary_expression->unary.value = left; \ \ sfunc(&unary_expression->unary); \ \ @@ -8627,7 +8610,7 @@ static void semantic_comparison(binary_expression_t *expression) &expression->base.source_position, type_left, type_right); } - expression->base.type = type_int; + expression->base.type = c_mode & _CXX ? type_bool : type_int; } /** @@ -8764,8 +8747,8 @@ static void semantic_logical_op(binary_expression_t *expression) type_t *const type_left = skip_typeref(orig_type_left); type_t *const type_right = skip_typeref(orig_type_right); - warn_function_address_as_bool(left); - warn_function_address_as_bool(right); + warn_reference_address_as_bool(left); + warn_reference_address_as_bool(right); if (!is_type_scalar(type_left) || !is_type_scalar(type_right)) { /* TODO: improve error message */ @@ -8776,7 +8759,7 @@ static void semantic_logical_op(binary_expression_t *expression) return; } - expression->base.type = type_int; + expression->base.type = c_mode & _CXX ? type_bool : type_int; } /** @@ -8953,8 +8936,7 @@ static void semantic_comma(binary_expression_t *expression) static expression_t *parse_##binexpression_type(expression_t *left) \ { \ expression_t *binexpr = allocate_expression_zero(binexpression_type); \ - binexpr->base.source_position = *HERE; \ - binexpr->binary.left = left; \ + binexpr->binary.left = left; \ eat(token_type); \ \ expression_t *right = parse_sub_expression(prec_r); \ @@ -9150,8 +9132,8 @@ static void init_expression_parsers(void) */ static asm_argument_t *parse_asm_arguments(bool is_out) { - asm_argument_t *result = NULL; - asm_argument_t *last = NULL; + asm_argument_t *result = NULL; + asm_argument_t **anchor = &result; while (token.type == T_STRING_LITERAL || token.type == '[') { asm_argument_t *argument = allocate_ast_zero(sizeof(argument[0])); @@ -9234,12 +9216,8 @@ static asm_argument_t *parse_asm_arguments(bool is_out) set_address_taken(expression, true); - if (last != NULL) { - last->next = argument; - } else { - result = argument; - } - last = argument; + *anchor = argument; + anchor = &argument->next; if (token.type != ',') break; @@ -9531,12 +9509,8 @@ static statement_t *parse_label_statement(void) } /* remember the labels in a list for later checking */ - if (label_last == NULL) { - label_first = &statement->label; - } else { - label_last->next = &statement->label; - } - label_last = &statement->label; + *label_anchor = &statement->label; + label_anchor = &statement->label.next; POP_PARENT; return statement; @@ -9559,6 +9533,7 @@ static statement_t *parse_if(void) add_anchor_token(')'); expression_t *const expr = parse_expression(); statement->ifs.condition = expr; + warn_reference_address_as_bool(expr); mark_vars_read(expr, NULL); rem_anchor_token(')'); expect(')'); @@ -9699,6 +9674,7 @@ static statement_t *parse_while(void) add_anchor_token(')'); expression_t *const cond = parse_expression(); statement->whiles.condition = cond; + warn_reference_address_as_bool(cond); mark_vars_read(cond, NULL); rem_anchor_token(')'); expect(')'); @@ -9732,6 +9708,7 @@ static statement_t *parse_do(void) add_anchor_token(')'); expression_t *const cond = parse_expression(); statement->do_while.condition = cond; + warn_reference_address_as_bool(cond); mark_vars_read(cond, NULL); rem_anchor_token(')'); expect(')'); @@ -9784,6 +9761,7 @@ static statement_t *parse_for(void) add_anchor_token(';'); expression_t *const cond = parse_expression(); statement->fors.condition = cond; + warn_reference_address_as_bool(cond); mark_vars_read(cond, NULL); rem_anchor_token(';'); } @@ -9801,7 +9779,7 @@ static statement_t *parse_for(void) rem_anchor_token(')'); statement->fors.body = parse_loop_body(statement); - assert(scope == &statement->fors.scope); + assert(current_scope == &statement->fors.scope); scope_pop(); environment_pop_to(top); @@ -9811,7 +9789,7 @@ static statement_t *parse_for(void) end_error: POP_PARENT; rem_anchor_token(')'); - assert(scope == &statement->fors.scope); + assert(current_scope == &statement->fors.scope); scope_pop(); environment_pop_to(top); @@ -9831,8 +9809,8 @@ static statement_t *parse_goto(void) expression_t *expression = parse_expression(); mark_vars_read(expression, NULL); - /* Argh: although documentation say the expression must be of type void *, - * gcc excepts anything that can be casted into void * without error */ + /* Argh: although documentation says the expression must be of type void*, + * gcc accepts anything that can be casted into void* without error */ type_t *type = expression->base.type; if (type != type_error_type) { @@ -9863,12 +9841,8 @@ static statement_t *parse_goto(void) } /* remember the goto's in a list for later checking */ - if (goto_last == NULL) { - goto_first = &statement->gotos; - } else { - goto_last->next = &statement->gotos; - } - goto_last = &statement->gotos; + *goto_anchor = &statement->gotos; + goto_anchor = &statement->gotos.next; expect(';'); @@ -9997,7 +9971,7 @@ static statement_t *parse_return(void) mark_vars_read(return_value, NULL); } - const type_t *const func_type = current_function->base.type; + const type_t *const func_type = skip_typeref(current_function->base.type); assert(is_type_function(func_type)); type_t *const return_type = skip_typeref(func_type->function.return_type); @@ -10045,18 +10019,18 @@ static statement_t *parse_declaration_statement(void) { statement_t *statement = allocate_statement_zero(STATEMENT_DECLARATION); - entity_t *before = scope->last_entity; + entity_t *before = current_scope->last_entity; if (GNU_MODE) parse_external_declaration(); else parse_declaration(record_entity); if (before == NULL) { - statement->declaration.declarations_begin = scope->entities; + statement->declaration.declarations_begin = current_scope->entities; } else { statement->declaration.declarations_begin = before->base.next; } - statement->declaration.declarations_end = scope->last_entity; + statement->declaration.declarations_end = current_scope->last_entity; return statement; } @@ -10151,15 +10125,15 @@ static statement_t *parse_local_label_declaration(void) goto end_error; } symbol_t *symbol = token.v.symbol; - entity_t *entity = get_entity(symbol, NAMESPACE_LOCAL_LABEL); - if (entity != NULL && entity->base.parent_scope == scope) { + entity_t *entity = get_entity(symbol, NAMESPACE_LABEL); + if (entity != NULL && entity->base.parent_scope == current_scope) { errorf(HERE, "multiple definitions of '__label__ %Y' (previous definition %P)", symbol, &entity->base.source_position); } else { entity = allocate_entity_zero(ENTITY_LOCAL_LABEL); - entity->base.parent_scope = scope; - entity->base.namespc = NAMESPACE_LOCAL_LABEL; + entity->base.parent_scope = current_scope; + entity->base.namespc = NAMESPACE_LABEL; entity->base.source_position = token.source_position; entity->base.symbol = symbol; @@ -10169,7 +10143,7 @@ static statement_t *parse_local_label_declaration(void) if (begin == NULL) begin = entity; - local_label_push(entity); + environment_push(entity); } next_token(); @@ -10184,6 +10158,55 @@ end_error: return statement; } +static void parse_namespace_definition(void) +{ + eat(T_namespace); + + entity_t *entity = NULL; + symbol_t *symbol = NULL; + + if (token.type == T_IDENTIFIER) { + symbol = token.v.symbol; + next_token(); + + entity = get_entity(symbol, NAMESPACE_NORMAL); + if (entity != NULL && entity->kind != ENTITY_NAMESPACE + && entity->base.parent_scope == current_scope) { + error_redefined_as_different_kind(&token.source_position, + entity, ENTITY_NAMESPACE); + entity = NULL; + } + } + + if (entity == NULL) { + entity = allocate_entity_zero(ENTITY_NAMESPACE); + entity->base.symbol = symbol; + entity->base.source_position = token.source_position; + entity->base.namespc = NAMESPACE_NORMAL; + entity->base.parent_scope = current_scope; + } + + if (token.type == '=') { + /* TODO: parse namespace alias */ + panic("namespace alias definition not supported yet"); + } + + environment_push(entity); + append_entity(current_scope, entity); + + size_t const top = environment_top(); + scope_push(&entity->namespacee.members); + + expect('{'); + parse_externals(); + expect('}'); + +end_error: + assert(current_scope == &entity->namespacee.members); + scope_pop(); + environment_pop_to(top); +} + /** * Parse a statement. * There's also parse_statement() which additionally checks for @@ -10247,22 +10270,22 @@ expression_statment: statement = parse_local_label_declaration(); break; - case ';': statement = parse_empty_statement(); break; - case '{': statement = parse_compound_statement(false); break; - case T___leave: statement = parse_leave_statement(); break; - case T___try: statement = parse_ms_try_statment(); break; - case T_asm: statement = parse_asm_statement(); break; - case T_break: statement = parse_break(); break; - case T_case: statement = parse_case_statement(); break; - case T_continue: statement = parse_continue(); break; - case T_default: statement = parse_default_statement(); break; - case T_do: statement = parse_do(); break; - case T_for: statement = parse_for(); break; - case T_goto: statement = parse_goto(); break; - case T_if: statement = parse_if(); break; - case T_return: statement = parse_return(); break; - case T_switch: statement = parse_switch(); break; - case T_while: statement = parse_while(); break; + case ';': statement = parse_empty_statement(); break; + case '{': statement = parse_compound_statement(false); break; + case T___leave: statement = parse_leave_statement(); break; + case T___try: statement = parse_ms_try_statment(); break; + case T_asm: statement = parse_asm_statement(); break; + case T_break: statement = parse_break(); break; + case T_case: statement = parse_case_statement(); break; + case T_continue: statement = parse_continue(); break; + case T_default: statement = parse_default_statement(); break; + case T_do: statement = parse_do(); break; + case T_for: statement = parse_for(); break; + case T_goto: statement = parse_goto(); break; + case T_if: statement = parse_if(); break; + case T_return: statement = parse_return(); break; + case T_switch: statement = parse_switch(); break; + case T_while: statement = parse_while(); break; EXPRESSION_START statement = parse_expression_statement(); @@ -10316,8 +10339,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) eat('{'); add_anchor_token('}'); - size_t const top = environment_top(); - size_t const top_local = local_label_top(); + size_t const top = environment_top(); scope_push(&statement->compound.scope); statement_t **anchor = &statement->compound.statements; @@ -10375,42 +10397,14 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) end_error: rem_anchor_token('}'); - assert(scope == &statement->compound.scope); + assert(current_scope == &statement->compound.scope); scope_pop(); environment_pop_to(top); - local_label_pop_to(top_local); POP_PARENT; return statement; } -/** - * Initialize builtin types. - */ -static void initialize_builtin_types(void) -{ - type_intmax_t = make_global_typedef("__intmax_t__", type_long_long); - type_size_t = make_global_typedef("__SIZE_TYPE__", type_unsigned_long); - type_ssize_t = make_global_typedef("__SSIZE_TYPE__", type_long); - type_ptrdiff_t = make_global_typedef("__PTRDIFF_TYPE__", type_long); - type_uintmax_t = make_global_typedef("__uintmax_t__", type_unsigned_long_long); - type_uptrdiff_t = make_global_typedef("__UPTRDIFF_TYPE__", type_unsigned_long); - type_wchar_t = make_global_typedef("__WCHAR_TYPE__", opt_short_wchar_t ? type_unsigned_short : type_int); - type_wint_t = make_global_typedef("__WINT_TYPE__", type_int); - - type_intmax_t_ptr = make_pointer_type(type_intmax_t, TYPE_QUALIFIER_NONE); - type_ptrdiff_t_ptr = make_pointer_type(type_ptrdiff_t, TYPE_QUALIFIER_NONE); - type_ssize_t_ptr = make_pointer_type(type_ssize_t, TYPE_QUALIFIER_NONE); - type_wchar_t_ptr = make_pointer_type(type_wchar_t, TYPE_QUALIFIER_NONE); - - /* const version of wchar_t */ - type_const_wchar_t = allocate_type_zero(TYPE_TYPEDEF); - type_const_wchar_t->typedeft.typedefe = type_wchar_t->typedeft.typedefe; - type_const_wchar_t->base.qualifiers |= TYPE_QUALIFIER_CONST; - - type_const_wchar_t_ptr = make_pointer_type(type_const_wchar_t, TYPE_QUALIFIER_NONE); -} - /** * Check for unused global static functions and variables */ @@ -10465,18 +10459,94 @@ static void parse_global_asm(void) end_error:; } -/** - * Parse a translation unit. - */ -static void parse_translation_unit(void) +static void parse_linkage_specification(void) +{ + eat(T_extern); + assert(token.type == T_STRING_LITERAL); + + const char *linkage = parse_string_literals().begin; + + linkage_kind_t old_linkage = current_linkage; + linkage_kind_t new_linkage; + if (strcmp(linkage, "C") == 0) { + new_linkage = LINKAGE_C; + } else if (strcmp(linkage, "C++") == 0) { + new_linkage = LINKAGE_CXX; + } else { + errorf(HERE, "linkage string \"%s\" not recognized", linkage); + new_linkage = LINKAGE_INVALID; + } + current_linkage = new_linkage; + + if (token.type == '{') { + next_token(); + parse_externals(); + expect('}'); + } else { + parse_external(); + } + +end_error: + assert(current_linkage == new_linkage); + current_linkage = old_linkage; +} + +static void parse_external(void) { + switch (token.type) { + DECLARATION_START_NO_EXTERN + case T_IDENTIFIER: + case T___extension__: + case '(': /* for function declarations with implicit return type and + * parenthesized declarator, i.e. (f)(void); */ + parse_external_declaration(); + return; + + case T_extern: + if (look_ahead(1)->type == T_STRING_LITERAL) { + parse_linkage_specification(); + } else { + parse_external_declaration(); + } + return; + + case T_asm: + parse_global_asm(); + return; + + case T_namespace: + parse_namespace_definition(); + return; + + case ';': + if (!strict_mode) { + if (warning.other) + warningf(HERE, "stray ';' outside of function"); + next_token(); + return; + } + /* FALLTHROUGH */ + + default: + errorf(HERE, "stray %K outside of function", &token); + if (token.type == '(' || token.type == '{' || token.type == '[') + eat_until_matching_token(token.type); + next_token(); + return; + } +} + +static void parse_externals(void) +{ + add_anchor_token('}'); add_anchor_token(T_EOF); #ifndef NDEBUG unsigned char token_anchor_copy[T_LAST_TOKEN]; memcpy(token_anchor_copy, token_anchor_set, sizeof(token_anchor_copy)); #endif - for (;;) { + + while (token.type != T_EOF && token.type != '}') { #ifndef NDEBUG bool anchor_leak = false; for (int i = 0; i != T_LAST_TOKEN; ++i) { @@ -10495,37 +10565,30 @@ static void parse_translation_unit(void) abort(); #endif - switch (token.type) { - DECLARATION_START - case T_IDENTIFIER: - case T___extension__: - parse_external_declaration(); - break; + parse_external(); + } - case T_asm: - parse_global_asm(); - break; + rem_anchor_token(T_EOF); + rem_anchor_token('}'); +} - case T_EOF: - rem_anchor_token(T_EOF); - return; +/** + * Parse a translation unit. + */ +static void parse_translation_unit(void) +{ + add_anchor_token(T_EOF); - case ';': - if (!strict_mode) { - if (warning.other) - warningf(HERE, "stray ';' outside of function"); - next_token(); - break; - } - /* FALLTHROUGH */ + while (true) { + parse_externals(); - default: - errorf(HERE, "stray %K outside of function", &token); - if (token.type == '(' || token.type == '{' || token.type == '[') - eat_until_matching_token(token.type); - next_token(); - break; - } + if (token.type == T_EOF) + break; + + errorf(HERE, "stray %K outside of function", &token); + if (token.type == '(' || token.type == '{' || token.type == '[') + eat_until_matching_token(token.type); + next_token(); } } @@ -10538,7 +10601,6 @@ void start_parsing(void) { environment_stack = NEW_ARR_F(stack_entry_t, 0); label_stack = NEW_ARR_F(stack_entry_t, 0); - local_label_stack = NEW_ARR_F(stack_entry_t, 0); diagnostic_count = 0; error_count = 0; warning_count = 0; @@ -10552,17 +10614,15 @@ void start_parsing(void) assert(file_scope == NULL); file_scope = &unit->scope; - assert(scope == NULL); + assert(current_scope == NULL); scope_push(&unit->scope); - - initialize_builtin_types(); } translation_unit_t *finish_parsing(void) { /* do NOT use scope_pop() here, this will crash, will it by hand */ - assert(scope == &unit->scope); - scope = NULL; + assert(current_scope == &unit->scope); + current_scope = NULL; assert(file_scope == &unit->scope); check_unused_globals(); @@ -10570,7 +10630,6 @@ translation_unit_t *finish_parsing(void) DEL_ARR_F(environment_stack); DEL_ARR_F(label_stack); - DEL_ARR_F(local_label_stack); translation_unit_t *result = unit; unit = NULL; @@ -10583,6 +10642,7 @@ void parse(void) for (int i = 0; i < MAX_LOOKAHEAD + 2; ++i) { next_token(); } + current_linkage = c_mode & _CXX ? LINKAGE_CXX : LINKAGE_C; parse_translation_unit(); }