X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=0325addd50a462ff1d8d0f35c77dfad761ec57f5;hb=b7aee7a7ddee373437c04479c6ec00f14639d4da;hp=dcd6cdc2c7f7b98da799a1ca3c997988bfa1534d;hpb=d2c97d08e22cfca07b4ac98ae8d4a9c5cb3b9261;p=cparser diff --git a/parser.c b/parser.c index dcd6cdc..0325add 100644 --- a/parser.c +++ b/parser.c @@ -84,6 +84,7 @@ struct declaration_specifiers_t { symbol_t *get_property_sym; /**< the name of the get property if set. */ symbol_t *put_property_sym; /**< the name of the put property if set. */ type_t *type; + variable_t *based_variable; /**< Microsoft __based variable. */ }; /** @@ -128,6 +129,7 @@ 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 entity_t *anonymous_entity; #define PUSH_PARENT(stmt) \ @@ -794,7 +796,7 @@ 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) { + for (; entity != NULL; entity = entity->base.symbol_next) { if (entity->base.namespc == namespc) return entity; } @@ -871,7 +873,7 @@ static void stack_pop_to(stack_entry_t **stack_ptr, size_t new_top) if (new_top == top) return; - for(i = top; i > new_top; --i) { + for (i = top; i > new_top; --i) { stack_entry_t *entry = &stack[i - 1]; entity_t *old_entity = entry->old_entity; @@ -1357,7 +1359,7 @@ static void parse_gnu_attribute_tls_model_arg(gnu_attribute_t *attribute) string_t string = { NULL, 0 }; parse_gnu_attribute_string_arg(attribute, &string); if (string.begin != NULL) { - for(size_t i = 0; i < 4; ++i) { + for (size_t i = 0; i < 4; ++i) { if (strcmp(tls_models[i], string.begin) == 0) { attribute->u.value = i; return; @@ -1382,7 +1384,7 @@ static void parse_gnu_attribute_visibility_arg(gnu_attribute_t *attribute) string_t string = { NULL, 0 }; parse_gnu_attribute_string_arg(attribute, &string); if (string.begin != NULL) { - for(size_t i = 0; i < 4; ++i) { + for (size_t i = 0; i < 4; ++i) { if (strcmp(visibilities[i], string.begin) == 0) { attribute->u.value = i; return; @@ -1406,7 +1408,7 @@ static void parse_gnu_attribute_model_arg(gnu_attribute_t *attribute) string_t string = { NULL, 0 }; parse_gnu_attribute_string_arg(attribute, &string); if (string.begin != NULL) { - for(int i = 0; i < 3; ++i) { + for (int i = 0; i < 3; ++i) { if (strcmp(visibilities[i], string.begin) == 0) { attribute->u.value = i; return; @@ -1472,7 +1474,7 @@ static void parse_gnu_attribute_interrupt_arg(gnu_attribute_t *attribute) string_t string = { NULL, 0 }; parse_gnu_attribute_string_arg(attribute, &string); if (string.begin != NULL) { - for(size_t i = 0; i < 5; ++i) { + for (size_t i = 0; i < 5; ++i) { if (strcmp(interrupts[i], string.begin) == 0) { attribute->u.value = i; return; @@ -1501,7 +1503,7 @@ static void parse_gnu_attribute_format_args(gnu_attribute_t *attribute) goto end_error; } const char *name = token.v.symbol->string; - for(i = 0; i < 4; ++i) { + for (i = 0; i < 4; ++i) { if (strcmp_underscore(format_names[i], name) == 0) break; } @@ -1656,7 +1658,7 @@ static decl_modifiers_t parse_gnu_attribute(gnu_attribute_t **attributes) next_token(); int i; - for(i = 0; i < GNU_AK_LAST; ++i) { + for (i = 0; i < GNU_AK_LAST; ++i) { if (strcmp_underscore(gnu_attribute_names[i], name) == 0) break; } @@ -2345,7 +2347,7 @@ static __attribute__((unused)) void debug_print_type_path( { size_t len = ARR_LEN(path->path); - for(size_t i = 0; i < len; ++i) { + for (size_t i = 0; i < len; ++i) { const type_path_entry_t *entry = & path->path[i]; type_t *type = skip_typeref(entry->type); @@ -2358,7 +2360,7 @@ static __attribute__((unused)) void debug_print_type_path( fprintf(stderr, ".%s", entry->v.compound_entry->base.symbol->string); } else if (is_type_array(type)) { - fprintf(stderr, "[%zu]", entry->v.index); + fprintf(stderr, "[%u]", (unsigned) entry->v.index); } else { fprintf(stderr, "-INVALID-"); } @@ -2455,7 +2457,7 @@ static void ascend_to(type_path_t *path, size_t top_path_level) static bool walk_designator(type_path_t *path, const designator_t *designator, bool used_in_offsetof) { - for( ; designator != NULL; designator = designator->next) { + for (; designator != NULL; designator = designator->next) { type_path_entry_t *top = get_type_path_top(path); type_t *orig_type = top->type; @@ -2476,7 +2478,7 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, } else { compound_t *compound = type->compound.compound; entity_t *iter = compound->members.entities; - for( ; iter != NULL; iter = iter->base.next) { + for (; iter != NULL; iter = iter->base.next) { if (iter->base.symbol == symbol) { break; } @@ -2945,7 +2947,7 @@ static compound_t *parse_compound_type_specifier(bool is_struct) eat(T_union); } - symbol_t *symbol = NULL; + symbol_t *symbol = NULL; compound_t *compound = NULL; if (token.type == T___attribute__) { @@ -3005,10 +3007,13 @@ static compound_t *parse_compound_type_specifier(bool is_struct) } if (token.type == '{') { - compound->complete = true; - parse_compound_type_entries(compound); modifiers |= parse_attributes(&attributes); + + if (symbol == NULL) { + assert(anonymous_entity == NULL); + anonymous_entity = (entity_t*)compound; + } } compound->modifiers |= modifiers; @@ -3020,8 +3025,8 @@ static void parse_enum_entries(type_t *const enum_type) eat('{'); if (token.type == '}') { - next_token(); errorf(HERE, "empty enum not allowed"); + next_token(); return; } @@ -3110,7 +3115,12 @@ static type_t *parse_enum_specifier(void) parse_enum_entries(type); parse_attributes(&attributes); - } else if(!entity->enume.complete && !(c_mode & _GNUC)) { + + if (symbol == NULL) { + assert(anonymous_entity == NULL); + anonymous_entity = entity; + } + } else if (!entity->enume.complete && !(c_mode & _GNUC)) { errorf(HERE, "enum %Y used before definition (incomplete enumes are a GNU extension)", symbol); } @@ -3404,6 +3414,40 @@ static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind) return entity; } +static void parse_microsoft_based(declaration_specifiers_t *specifiers) +{ + if (token.type != T_IDENTIFIER) { + parse_error_expected("while parsing __based", T_IDENTIFIER, NULL); + return; + } + symbol_t *symbol = token.v.symbol; + entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL); + + if (entity == NULL || entity->base.kind != ENTITY_VARIABLE) { + errorf(HERE, "'%Y' is not a variable name.", symbol); + entity = create_error_entity(symbol, ENTITY_VARIABLE); + } else { + variable_t *variable = &entity->variable; + + if (specifiers->based_variable != NULL) { + errorf(HERE, "__based type qualifier specified more than once"); + } + specifiers->based_variable = variable; + + type_t *const type = variable->base.type; + + if (is_type_valid(type)) { + if (! is_type_pointer(skip_typeref(type))) { + errorf(HERE, "variable in __based modifier must have pointer type instead of %T", type); + } + if (variable->base.base.parent_scope != file_scope) { + errorf(HERE, "a nonstatic local variable may not be used in a __based specification"); + } + } + } + next_token(); +} + /** * Finish the construction of a struct type by calculating * its size, offsets, alignment. @@ -3547,6 +3591,15 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) expect(')'); break; + case T__based: + next_token(); + expect('('); + add_anchor_token(')'); + parse_microsoft_based(specifiers); + rem_anchor_token(')'); + expect(')'); + break; + case T___thread: switch (specifiers->storage_class) { case STORAGE_CLASS_NONE: @@ -4016,6 +4069,7 @@ static entity_t *parse_parameter(void) parse_declaration_specifiers(&specifiers); entity_t *entity = parse_declarator(&specifiers, true, false); + anonymous_entity = NULL; return entity; } @@ -4201,53 +4255,27 @@ end_error: return (construct_type_t*) array; } -static construct_type_t *parse_function_declarator(scope_t *scope) +static construct_type_t *parse_function_declarator(scope_t *scope, + decl_modifiers_t modifiers) { - 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; + type_t *type = allocate_type_zero(TYPE_FUNCTION); + function_type_t *ftype = &type->function; - unsigned mask = modifiers & (DM_CDECL|DM_STDCALL|DM_FASTCALL|DM_THISCALL); + ftype->linkage = current_linkage; - if (mask & (mask-1)) { - const char *first = NULL, *second = NULL; + switch (modifiers & (DM_CDECL | DM_STDCALL | DM_FASTCALL | DM_THISCALL)) { + case DM_NONE: break; + case DM_CDECL: ftype->calling_convention = CC_CDECL; break; + case DM_STDCALL: ftype->calling_convention = CC_STDCALL; break; + case DM_FASTCALL: ftype->calling_convention = CC_FASTCALL; break; + case DM_THISCALL: ftype->calling_convention = CC_THISCALL; break; - /* more than one calling convention set */ - if (modifiers & DM_CDECL) { - if (first == NULL) first = "cdecl"; - else if (second == NULL) second = "cdecl"; - } - if (modifiers & DM_STDCALL) { - if (first == NULL) first = "stdcall"; - else if (second == NULL) second = "stdcall"; - } - if (modifiers & DM_FASTCALL) { - if (first == NULL) first = "fastcall"; - else if (second == NULL) second = "fastcall"; - } - if (modifiers & DM_THISCALL) { - if (first == NULL) first = "thiscall"; - else if (second == NULL) second = "thiscall"; - } - errorf(&entity->base.source_position, - "%s and %s attributes are not compatible", first, second); + default: + errorf(HERE, "multiple calling conventions in declaration"); + break; } - if (modifiers & DM_CDECL) - type->function.calling_convention = CC_CDECL; - else if (modifiers & DM_STDCALL) - type->function.calling_convention = CC_STDCALL; - else if (modifiers & DM_FASTCALL) - type->function.calling_convention = CC_FASTCALL; - else if (modifiers & DM_THISCALL) - type->function.calling_convention = CC_THISCALL; -#endif - - parse_parameters(&type->function, scope); + parse_parameters(ftype, scope); construct_function_type_t *construct_function_type = obstack_alloc(&temp_obst, sizeof(construct_function_type[0])); @@ -4292,8 +4320,10 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env, modifiers |= parse_attributes(&attributes); } - if (env != NULL) - env->modifiers |= modifiers; + if (env != NULL) { + modifiers |= env->modifiers; + env->modifiers = modifiers; + } construct_type_t *inner_types = NULL; @@ -4328,7 +4358,7 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env, construct_type_t *p = last; - while(true) { + while (true) { construct_type_t *type; switch (token.type) { case '(': { @@ -4336,7 +4366,7 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env, if (env != NULL) scope = &env->parameters; - type = parse_function_declarator(scope); + type = parse_function_declarator(scope, modifiers); break; } case '[': @@ -4448,10 +4478,10 @@ static void parse_declaration_attributes(entity_t *entity) } static type_t *construct_declarator_type(construct_type_t *construct_list, - type_t *type) + type_t *type, variable_t *variable) { construct_type_t *iter = construct_list; - for( ; iter != NULL; iter = iter->next) { + for (; iter != NULL; iter = iter->next) { switch (iter->kind) { case CONSTRUCT_INVALID: internal_errorf(HERE, "invalid type construction found"); @@ -4482,7 +4512,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, case CONSTRUCT_POINTER: { parsed_pointer_t *parsed_pointer = (parsed_pointer_t*) iter; - type = make_pointer_type(type, parsed_pointer->type_qualifiers); + type = make_based_pointer_type(type, parsed_pointer->type_qualifiers, variable); continue; } @@ -4544,10 +4574,11 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, { parse_declarator_env_t env; memset(&env, 0, sizeof(env)); + env.modifiers = specifiers->modifiers; construct_type_t *construct_type = parse_inner_declarator(&env, may_be_abstract); - type_t *type = construct_declarator_type(construct_type, specifiers->type); + type_t *type = construct_declarator_type(construct_type, specifiers->type, specifiers->based_variable); if (construct_type != NULL) { obstack_free(&temp_obst, construct_type); @@ -4559,6 +4590,21 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, entity->base.symbol = env.symbol; entity->base.source_position = env.source_position; entity->typedefe.type = type; + + if (anonymous_entity != NULL) { + if (is_type_compound(type)) { + assert(anonymous_entity->compound.alias == NULL); + assert(anonymous_entity->kind == ENTITY_STRUCT || + anonymous_entity->kind == ENTITY_UNION); + anonymous_entity->compound.alias = entity; + anonymous_entity = NULL; + } else if (is_type_enum(type)) { + assert(anonymous_entity->enume.alias == NULL); + assert(anonymous_entity->kind == ENTITY_ENUM); + anonymous_entity->enume.alias = entity; + anonymous_entity = NULL; + } + } } else { if (create_compound_member) { entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER); @@ -4583,11 +4629,11 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, } } - entity->base.source_position = env.source_position; - entity->base.symbol = env.symbol; - entity->base.namespc = NAMESPACE_NORMAL; - entity->declaration.type = type; - entity->declaration.modifiers = env.modifiers | specifiers->modifiers; + entity->base.source_position = env.source_position; + entity->base.symbol = env.symbol; + entity->base.namespc = NAMESPACE_NORMAL; + entity->declaration.type = type; + entity->declaration.modifiers = env.modifiers; entity->declaration.deprecated_string = specifiers->deprecated_string; storage_class_t storage_class = specifiers->storage_class; @@ -4609,7 +4655,7 @@ static type_t *parse_abstract_declarator(type_t *base_type) { construct_type_t *construct_type = parse_inner_declarator(NULL, 1); - type_t *result = construct_declarator_type(construct_type, base_type); + type_t *result = construct_declarator_type(construct_type, base_type, NULL); if (construct_type != NULL) { obstack_free(&temp_obst, construct_type); } @@ -5063,7 +5109,7 @@ static void parse_declaration_rest(entity_t *ndeclaration, { add_anchor_token(';'); add_anchor_token(','); - while(true) { + while (true) { entity_t *entity = finished_declaration(ndeclaration, token.type == '='); if (token.type == '=') { @@ -5081,6 +5127,7 @@ static void parse_declaration_rest(entity_t *ndeclaration, expect(';'); end_error: + anonymous_entity = NULL; rem_anchor_token(';'); rem_anchor_token(','); } @@ -5181,7 +5228,7 @@ static void parse_kr_declaration_list(entity_t *entity) function_parameter_t *last_parameter = NULL; entity_t *parameter_declaration = entity->function.parameters.entities; - for( ; parameter_declaration != NULL; + for (; parameter_declaration != NULL; parameter_declaration = parameter_declaration->base.next) { type_t *parameter_type = parameter_declaration->declaration.type; if (parameter_type == NULL) { @@ -5942,7 +5989,7 @@ static void parse_external_declaration(void) scope_push(&function->parameters); entity_t *parameter = function->parameters.entities; - for( ; parameter != NULL; parameter = parameter->base.next) { + for (; parameter != NULL; parameter = parameter->base.next) { if (parameter->base.parent_scope == &ndeclaration->function.parameters) { parameter->base.parent_scope = current_scope; } @@ -6027,14 +6074,11 @@ static type_t *make_bitfield_type(type_t *base_type, expression_t *size, long v = fold_constant(size); if (v < 0) { - errorf(source_position, "negative width in bit-field '%Y'", - symbol); + errorf(source_position, "negative width in bit-field '%Y'", symbol); } else if (v == 0) { - errorf(source_position, "zero width for bit-field '%Y'", - symbol); + errorf(source_position, "zero width for bit-field '%Y'", symbol); } else if (bit_size > 0 && (il_size_t)v > bit_size) { - errorf(source_position, "width of '%Y' exceeds its type", - symbol); + errorf(source_position, "width of '%Y' exceeds its type", symbol); } else { type->bitfield.bit_size = v; } @@ -6046,11 +6090,13 @@ static type_t *make_bitfield_type(type_t *base_type, expression_t *size, static entity_t *find_compound_entry(compound_t *compound, symbol_t *symbol) { entity_t *iter = compound->members.entities; - for( ; iter != NULL; iter = iter->base.next) { + for (; iter != NULL; iter = iter->base.next) { if (iter->kind != ENTITY_COMPOUND_MEMBER) continue; - if (iter->base.symbol == NULL) { + if (iter->base.symbol == symbol) { + return iter; + } else if (iter->base.symbol == NULL) { type_t *type = skip_typeref(iter->declaration.type); if (is_type_compound(type)) { entity_t *result @@ -6060,10 +6106,6 @@ static entity_t *find_compound_entry(compound_t *compound, symbol_t *symbol) } continue; } - - if (iter->base.symbol == symbol) { - return iter; - } } return NULL; @@ -6114,7 +6156,6 @@ static void parse_compound_declarators(compound_t *compound, entity_t *prev = find_compound_entry(compound, symbol); if (prev != NULL) { - assert(prev->base.symbol == symbol); errorf(&entity->base.source_position, "multiple declarations of symbol '%Y' (declared %P)", symbol, &prev->base.source_position); @@ -6123,40 +6164,33 @@ static void parse_compound_declarators(compound_t *compound, append_entity(&compound->members, entity); - if (token.type != ',') - break; - next_token(); - } - expect(';'); - -end_error: - ; -} - -static void semantic_compound(compound_t *compound) -{ - entity_t *entity = compound->members.entities; - for ( ; entity != NULL; entity = entity->base.next) { - assert(entity->kind == ENTITY_COMPOUND_MEMBER); - type_t *orig_type = entity->declaration.type; type_t *type = skip_typeref(orig_type); - if (is_type_function(type)) { - errorf(HERE, - "compound member '%Y' must not have function type '%T'", - entity->base.symbol, orig_type); + errorf(&entity->base.source_position, + "compound member '%Y' must not have function type '%T'", + entity->base.symbol, orig_type); } else if (is_type_incomplete(type)) { - /* §6.7.2.1 (16) flexible array member */ - if (is_type_array(type) && entity->base.next == NULL) { + /* §6.7.2.1:16 flexible array member */ + if (is_type_array(type) && + token.type == ';' && + look_ahead(1)->type == '}') { compound->has_flexible_member = true; } else { - errorf(HERE, - "compound member '%Y' has incomplete type '%T'", - entity->base.symbol, orig_type); + errorf(&entity->base.source_position, + "compound member '%Y' has incomplete type '%T'", + entity->base.symbol, orig_type); } } + + if (token.type != ',') + break; + next_token(); } + expect(';'); + +end_error: + anonymous_entity = NULL; } static void parse_compound_type_entries(compound_t *compound) @@ -6175,9 +6209,11 @@ static void parse_compound_type_entries(compound_t *compound) parse_compound_declarators(compound, &specifiers); } - semantic_compound(compound); rem_anchor_token('}'); next_token(); + + /* §6.7.2.1:7 */ + compound->complete = true; } static type_t *parse_typename(void) @@ -6911,7 +6947,7 @@ static designator_t *parse_designator(void) next_token(); designator_t *last_designator = result; - while(true) { + while (true) { if (token.type == '.') { next_token(); if (token.type != T_IDENTIFIER) { @@ -7302,7 +7338,7 @@ static expression_t *parse_noop_expression(void) add_anchor_token(','); if (token.type != ')') { - while(true) { + while (true) { (void)parse_assignment_expression(); if (token.type != ',') break; @@ -7442,8 +7478,6 @@ static expression_t *parse_typeprop(expression_kind_t const kind) eat(kind == EXPR_SIZEOF ? T_sizeof : T___alignof__); - char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof"; - /* we only refer to a type property, mark this case */ bool old = in_type_prop; in_type_prop = true; @@ -7481,6 +7515,7 @@ typeprop_expression: type->kind == TYPE_BITFIELD ? "bitfield" : NULL; if (wrong_type != NULL) { + char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof"; errorf(&tp_expression->base.source_position, "operand of %s expression must not be of %s type '%T'", what, wrong_type, orig_type); @@ -7717,7 +7752,7 @@ static expression_t *parse_call_expression(expression_t *expression) } /* do default promotion */ - for( ; argument != NULL; argument = argument->next) { + for (; argument != NULL; argument = argument->next) { type_t *type = argument->expression->base.type; type = get_default_promoted_type(type); @@ -8999,7 +9034,7 @@ static expression_t *parse_sub_expression(precedence_t precedence) assert(left != NULL); left->base.source_position = source_position; - while(true) { + while (true) { if (token.type < 0) { return expected_expression_error(); } @@ -9238,7 +9273,7 @@ static asm_clobber_t *parse_asm_clobbers(void) asm_clobber_t *result = NULL; asm_clobber_t *last = NULL; - while(token.type == T_STRING_LITERAL) { + while (token.type == T_STRING_LITERAL) { asm_clobber_t *clobber = allocate_ast_zero(sizeof(clobber[0])); clobber->clobber = parse_string_literals(); @@ -10380,7 +10415,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) /* look over all statements again to produce no effect warnings */ if (warning.unused_value) { statement_t *sub_statement = statement->compound.statements; - for( ; sub_statement != NULL; sub_statement = sub_statement->base.next) { + for (; sub_statement != NULL; sub_statement = sub_statement->base.next) { if (sub_statement->kind != STATEMENT_EXPRESSION) continue; /* don't emit a warning for the last expression in an expression