X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=fdc013d9c998b1b86c3a6314ca3bd89002ca820d;hb=776944099aee0467915e9ea4f3c2f3f10f742aaa;hp=d07dd21d880917c20957036d9de1251948c87bc5;hpb=f894ab556ac1b28843b78f95de1ee399574408fd;p=cparser diff --git a/parser.c b/parser.c index d07dd21..fdc013d 100644 --- a/parser.c +++ b/parser.c @@ -23,6 +23,7 @@ #include #include +#include "adt/strutil.h" #include "parser.h" #include "diagnostic.h" #include "format_check.h" @@ -1071,22 +1072,6 @@ static string_t parse_string_literals(void) return result; } -/** - * compare two string, ignoring double underscores on the second. - */ -static int strcmp_underscore(const char *s1, const char *s2) -{ - if (s2[0] == '_' && s2[1] == '_') { - size_t len2 = strlen(s2); - size_t len1 = strlen(s1); - if (len1 == len2-4 && s2[len2-2] == '_' && s2[len2-1] == '_') { - return strncmp(s1, s2+2, len2-4); - } - } - - return strcmp(s1, s2); -} - static attribute_t *allocate_attribute_zero(attribute_kind_t kind) { attribute_t *attribute = allocate_ast_zero(sizeof(*attribute)); @@ -1231,8 +1216,7 @@ static attribute_t *parse_attribute_gnu_single(void) } const char *attribute_name = get_attribute_name(kind); - if (attribute_name != NULL - && strcmp_underscore(attribute_name, name) == 0) + if (attribute_name != NULL && streq_underscore(attribute_name, name)) break; } @@ -1537,7 +1521,7 @@ unary: determine_lhs_ent(expr->va_starte.ap, lhs_ent); return; - EXPR_LITERAL_CASES + case EXPR_LITERAL_CASES: case EXPR_ERROR: case EXPR_STRING_LITERAL: case EXPR_WIDE_STRING_LITERAL: @@ -1681,15 +1665,6 @@ static initializer_t *initializer_from_expression(type_t *orig_type, return result; } -/** - * Checks if a given expression can be used as a constant initializer. - */ -static bool is_initializer_constant(const expression_t *expression) -{ - return is_constant_expression(expression) != EXPR_CLASS_VARIABLE || - is_linker_constant(expression) != EXPR_CLASS_VARIABLE; -} - /** * Parses an scalar initializer. * @@ -1710,7 +1685,7 @@ static initializer_t *parse_scalar_initializer(type_t *type, expression_t *expression = parse_assignment_expression(); mark_vars_read(expression, NULL); - if (must_be_constant && !is_initializer_constant(expression)) { + if (must_be_constant && !is_linker_constant(expression)) { errorf(&expression->base.source_position, "initialisation expression '%E' is not constant", expression); @@ -1833,11 +1808,10 @@ static void descend_into_subtype(type_path_t *path) top->type = top_type; if (is_type_compound(top_type)) { - compound_t *compound = top_type->compound.compound; - entity_t *entry = compound->members.entities; + compound_t *const compound = top_type->compound.compound; + entity_t *const entry = skip_unnamed_bitfields(compound->members.entities); if (entry != NULL) { - assert(entry->kind == ENTITY_COMPOUND_MEMBER); top->v.compound_entry = &entry->declaration; path->top_type = entry->declaration.type; } else { @@ -1977,7 +1951,7 @@ static void advance_current_object(type_path_t *path, size_t top_path_level) } else if (is_type_struct(type)) { declaration_t *entry = top->v.compound_entry; - entity_t *next_entity = entry->base.next; + entity_t *const next_entity = skip_unnamed_bitfields(entry->base.next); if (next_entity != NULL) { assert(is_declaration(next_entity)); entry = &next_entity->declaration; @@ -2131,7 +2105,7 @@ finish_designator: expression_t *expression = parse_assignment_expression(); mark_vars_read(expression, NULL); - if (env->must_be_constant && !is_initializer_constant(expression)) { + if (env->must_be_constant && !is_linker_constant(expression)) { errorf(&expression->base.source_position, "Initialisation expression '%E' is not constant", expression); @@ -2628,9 +2602,9 @@ static attribute_t *parse_attribute_ms_property(attribute_t *attribute) symbol_t **prop; symbol_t *symbol = token.identifier.symbol; - if (strcmp(symbol->string, "put") == 0) { + if (streq(symbol->string, "put")) { prop = &property->put_symbol; - } else if (strcmp(symbol->string, "get") == 0) { + } else if (streq(symbol->string, "get")) { prop = &property->get_symbol; } else { errorf(HERE, "expected put or get in property declspec"); @@ -2666,7 +2640,7 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void) for (attribute_kind_t k = ATTRIBUTE_MS_FIRST; k <= ATTRIBUTE_MS_LAST; ++k) { const char *attribute_name = get_attribute_name(k); - if (attribute_name != NULL && strcmp(attribute_name, name) == 0) { + if (attribute_name != NULL && streq(attribute_name, name)) { kind = k; break; } @@ -3889,6 +3863,10 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, handle_entity_attributes(attributes, entity); } + if (entity->kind == ENTITY_FUNCTION && !freestanding) { + adapt_special_functions(&entity->function); + } + return entity; } @@ -3979,7 +3957,7 @@ warn_arg_count: */ static bool is_sym_main(const symbol_t *const sym) { - return strcmp(sym->string, "main") == 0; + return streq(sym->string, "main"); } static void error_redefined_as_different_kind(const source_position_t *pos, @@ -4105,8 +4083,22 @@ entity_t *record_entity(entity_t *entity, const bool is_definition) goto finish; } if (previous_entity->kind == ENTITY_TYPEDEF) { - /* TODO: C++ allows this for exactly the same type */ - errorf(pos, "redefinition of '%N' (declared %P)", entity, ppos); + type_t *const type = skip_typeref(entity->typedefe.type); + type_t *const prev_type + = skip_typeref(previous_entity->typedefe.type); + if (c_mode & _CXX) { + /* C++ allows double typedef if they are identical + * (after skipping typedefs) */ + if (type == prev_type) + goto finish; + } else { + /* GCC extension: redef in system headers is allowed */ + if ((pos->is_system_header || ppos->is_system_header) && + types_compatible(type, prev_type)) + goto finish; + } + errorf(pos, "redefinition of '%N' (declared %P)", + entity, ppos); goto finish; } @@ -4186,7 +4178,7 @@ warn_redundant_declaration: ; merge_in_attributes(decl, prev_decl->attributes); } else if (!is_definition && is_type_valid(prev_type) && - strcmp(ppos->input_name, "") != 0) { + !pos->is_system_header) { warningf(WARN_REDUNDANT_DECLS, pos, "redundant declaration for '%Y' (declared %P)", symbol, ppos); } } else if (current_function == NULL) { @@ -4731,10 +4723,12 @@ static bool expression_returns(expression_t const *const expr) switch (expr->kind) { case EXPR_CALL: { expression_t const *const func = expr->call.function; - if (func->kind == EXPR_REFERENCE) { - entity_t *entity = func->reference.entity; - if (entity->kind == ENTITY_FUNCTION - && entity->declaration.modifiers & DM_NORETURN) + type_t const *const type = skip_typeref(func->base.type); + if (type->kind == TYPE_POINTER) { + type_t const *const points_to + = skip_typeref(type->pointer.points_to); + if (points_to->kind == TYPE_FUNCTION + && points_to->function.modifiers & DM_NORETURN) return false; } @@ -4751,7 +4745,7 @@ static bool expression_returns(expression_t const *const expr) case EXPR_REFERENCE: case EXPR_REFERENCE_ENUM_VALUE: - EXPR_LITERAL_CASES + case EXPR_LITERAL_CASES: case EXPR_STRING_LITERAL: case EXPR_WIDE_STRING_LITERAL: case EXPR_COMPOUND_LITERAL: // TODO descend into initialisers @@ -4804,13 +4798,13 @@ static bool expression_returns(expression_t const *const expr) case EXPR_VA_COPY: return expression_returns(expr->va_copye.src); - EXPR_UNARY_CASES_MANDATORY + case EXPR_UNARY_CASES_MANDATORY: return expression_returns(expr->unary.value); case EXPR_UNARY_THROW: return false; - EXPR_BINARY_CASES + case EXPR_BINARY_CASES: // TODO handle constant lhs of && and || return expression_returns(expr->binary.left) && @@ -5320,6 +5314,22 @@ warn_unreachable: } } +static bool is_main(entity_t *entity) +{ + static symbol_t *sym_main = NULL; + if (sym_main == NULL) { + sym_main = symbol_table_insert("main"); + } + + if (entity->base.symbol != sym_main) + return false; + /* must be in outermost scope */ + if (entity->base.parent_scope != file_scope) + return false; + + return true; +} + static void parse_external_declaration(void) { /* function-definitions and declarations both start with declaration @@ -5469,6 +5479,9 @@ static void parse_external_declaration(void) } } + if (is_main(entity) && enable_main_collect2_hack) + prepare_main_collect2(entity); + POP_PARENT(); assert(current_function == function); assert(current_entity == entity); @@ -5704,6 +5717,8 @@ static void parse_compound_declarators(compound_t *compound, token.kind != ';' || look_ahead(1)->kind != '}') { errorf(pos, "'%N' has incomplete type '%T'", entity, orig_type); + } else if (compound->members.entities == NULL) { + errorf(pos, "flexible array member in otherwise empty struct"); } } } @@ -6187,7 +6202,8 @@ static entity_t *parse_qualified_identifier(void) if (entity == NULL) { if (!strict_mode && token.kind == '(') { /* an implicitly declared function */ - warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos, "implicit declaration of function '%Y'", symbol); + warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos, + "implicit declaration of function '%Y'", symbol); entity = create_implicit_function(symbol, &pos); } else { errorf(&pos, "unknown identifier '%Y' found.", symbol); @@ -7193,32 +7209,25 @@ static void check_call_argument(type_t *expected_type, /** * Handle the semantic restrictions of builtin calls */ -static void handle_builtin_argument_restrictions(call_expression_t *call) { - switch (call->function->reference.entity->function.btk) { - case bk_gnu_builtin_return_address: - case bk_gnu_builtin_frame_address: { +static void handle_builtin_argument_restrictions(call_expression_t *call) +{ + entity_t *entity = call->function->reference.entity; + switch (entity->function.btk) { + case BUILTIN_FIRM: + switch (entity->function.b.firm_builtin_kind) { + case ir_bk_return_address: + case ir_bk_frame_address: { /* argument must be constant */ call_argument_t *argument = call->arguments; if (is_constant_expression(argument->expression) == EXPR_CLASS_VARIABLE) { errorf(&call->base.source_position, - "argument of '%Y' must be a constant expression", - call->function->reference.entity->base.symbol); - } - break; - } - case bk_gnu_builtin_object_size: - if (call->arguments == NULL) - break; - - call_argument_t *arg = call->arguments->next; - if (arg != NULL && is_constant_expression(arg->expression) == EXPR_CLASS_VARIABLE) { - errorf(&call->base.source_position, - "second argument of '%Y' must be a constant expression", + "argument of '%Y' must be a constant expression", call->function->reference.entity->base.symbol); } break; - case bk_gnu_builtin_prefetch: + } + case ir_bk_prefetch: /* second and third argument must be constant if existent */ if (call->arguments == NULL) break; @@ -7228,22 +7237,37 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) { if (rw != NULL) { if (is_constant_expression(rw->expression) == EXPR_CLASS_VARIABLE) { errorf(&call->base.source_position, - "second argument of '%Y' must be a constant expression", - call->function->reference.entity->base.symbol); + "second argument of '%Y' must be a constant expression", + call->function->reference.entity->base.symbol); } locality = rw->next; } if (locality != NULL) { if (is_constant_expression(locality->expression) == EXPR_CLASS_VARIABLE) { errorf(&call->base.source_position, - "third argument of '%Y' must be a constant expression", - call->function->reference.entity->base.symbol); + "third argument of '%Y' must be a constant expression", + call->function->reference.entity->base.symbol); } locality = rw->next; } break; default: break; + } + + case BUILTIN_OBJECT_SIZE: + if (call->arguments == NULL) + break; + + call_argument_t *arg = call->arguments->next; + if (arg != NULL && is_constant_expression(arg->expression) == EXPR_CLASS_VARIABLE) { + errorf(&call->base.source_position, + "second argument of '%Y' must be a constant expression", + call->function->reference.entity->base.symbol); + } + break; + default: + break; } } @@ -7339,7 +7363,7 @@ static expression_t *parse_call_expression(expression_t *expression) if (expression->kind == EXPR_REFERENCE) { reference_expression_t *reference = &expression->reference; if (reference->entity->kind == ENTITY_FUNCTION && - reference->entity->function.btk != bk_none) + reference->entity->function.btk != BUILTIN_NONE) handle_builtin_argument_restrictions(call); } @@ -9072,7 +9096,22 @@ static statement_t *parse_case_statement(void) eat(T_case); - expression_t *const expression = parse_expression(); + expression_t *expression = parse_expression(); + type_t *expression_type = expression->base.type; + type_t *skipped = skip_typeref(expression_type); + if (!is_type_integer(skipped) && is_type_valid(skipped)) { + errorf(pos, "case expression '%E' must have integer type but has type '%T'", + expression, expression_type); + } + + type_t *type = expression_type; + if (current_switch != NULL) { + type_t *switch_type = current_switch->expression->base.type; + if (is_type_valid(switch_type)) { + expression = create_implicit_cast(expression, switch_type); + } + } + statement->case_label.expression = expression; expression_classification_t const expr_class = is_constant_expression(expression); if (expr_class != EXPR_CLASS_CONSTANT) { @@ -9088,7 +9127,15 @@ static statement_t *parse_case_statement(void) if (GNU_MODE) { if (next_if(T_DOTDOTDOT)) { - expression_t *const end_range = parse_expression(); + expression_t *end_range = parse_expression(); + expression_type = expression->base.type; + skipped = skip_typeref(expression_type); + if (!is_type_integer(skipped) && is_type_valid(skipped)) { + errorf(pos, "case expression '%E' must have integer type but has type '%T'", + expression, expression_type); + } + + end_range = create_implicit_cast(end_range, type); statement->case_label.end_range = end_range; expression_classification_t const end_class = is_constant_expression(end_range); if (end_class != EXPR_CLASS_CONSTANT) { @@ -10361,9 +10408,9 @@ static void parse_linkage_specification(void) linkage_kind_t old_linkage = current_linkage; linkage_kind_t new_linkage; - if (strcmp(linkage, "C") == 0) { + if (streq(linkage, "C")) { new_linkage = LINKAGE_C; - } else if (strcmp(linkage, "C++") == 0) { + } else if (streq(linkage, "C++")) { new_linkage = LINKAGE_CXX; } else { errorf(&pos, "linkage string \"%s\" not recognized", linkage); @@ -10561,6 +10608,8 @@ static void complete_incomplete_arrays(void) void prepare_main_collect2(entity_t *entity) { + PUSH_SCOPE(&entity->function.statement->compound.scope); + // create call to __main symbol_t *symbol = symbol_table_insert("__main"); entity_t *subsubmain_ent @@ -10587,6 +10636,8 @@ void prepare_main_collect2(entity_t *entity) expr_statement->base.next = compounds->statements; compounds->statements = expr_statement; + + POP_SCOPE(); } void parse(void)