X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=2a8f26928c3ec6bd79b6e80d3a4a938908085902;hb=442cc935f91c445283176287cd3c6fe536416bf7;hp=8e014d1a7f5733041f9729cb0a96535c0689c84b;hpb=6f244aaeb03fb7f14d24aacfcf39a347b26b87c7;p=cparser diff --git a/parser.c b/parser.c index 8e014d1..2a8f269 100644 --- a/parser.c +++ b/parser.c @@ -42,7 +42,7 @@ #include "adt/array.h" //#define PRINT_TOKENS -#define MAX_LOOKAHEAD 2 +#define MAX_LOOKAHEAD 1 typedef struct { entity_t *old_entity; @@ -65,7 +65,7 @@ struct gnu_attribute_t { union { size_t value; string_t string; - atomic_type_kind_t akind; + symbol_t *symbol; long argument; /**< Single argument. */ argument_list_t *arguments; /**< List of argument expressions. */ } u; @@ -113,7 +113,7 @@ static token_t token; /** The lookahead ring-buffer. */ static token_t lookahead_buffer[MAX_LOOKAHEAD]; /** Position of the next token in the lookahead buffer. */ -static int lookahead_bufpos; +static size_t lookahead_bufpos; static stack_entry_t *environment_stack = NULL; static stack_entry_t *label_stack = NULL; static scope_t *file_scope = NULL; @@ -351,7 +351,7 @@ static size_t get_entity_struct_size(entity_kind_t kind) [ENTITY_LOCAL_LABEL] = sizeof(label_t), [ENTITY_NAMESPACE] = sizeof(namespace_t) }; - assert(kind < sizeof(sizes) / sizeof(sizes[0])); + assert(kind < lengthof(sizes)); assert(sizes[kind] != 0); return sizes[kind]; } @@ -396,7 +396,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 < lengthof(sizes)); assert(sizes[kind] != 0); return sizes[kind]; } @@ -443,7 +443,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 < lengthof(sizes)); assert(sizes[kind] != 0); return sizes[kind]; } @@ -526,7 +526,7 @@ static size_t get_type_struct_size(type_kind_t kind) [TYPE_TYPEDEF] = sizeof(typedef_type_t), [TYPE_TYPEOF] = sizeof(typeof_type_t), }; - assert(sizeof(sizes) / sizeof(sizes[0]) == (int) TYPE_TYPEOF + 1); + assert(lengthof(sizes) == (int)TYPE_TYPEOF + 1); assert(kind <= TYPE_TYPEOF); assert(sizes[kind] != 0); return sizes[kind]; @@ -562,7 +562,7 @@ static size_t get_initializer_size(initializer_kind_t kind) [INITIALIZER_LIST] = sizeof(initializer_list_t), [INITIALIZER_DESIGNATOR] = sizeof(initializer_designator_t) }; - assert(kind < sizeof(sizes) / sizeof(*sizes)); + assert(kind < lengthof(sizes)); assert(sizes[kind] != 0); return sizes[kind]; } @@ -579,14 +579,6 @@ static initializer_t *allocate_initializer_zero(initializer_kind_t kind) return result; } -/** - * Free a type from the type obstack. - */ -static void free_type(void *type) -{ - obstack_free(type_obst, type); -} - /** * Returns the index of the top element of the environment stack. */ @@ -612,7 +604,7 @@ static inline void next_token(void) lookahead_buffer[lookahead_bufpos] = lexer_token; lexer_next_token(); - lookahead_bufpos = (lookahead_bufpos+1) % MAX_LOOKAHEAD; + lookahead_bufpos = (lookahead_bufpos + 1) % MAX_LOOKAHEAD; #ifdef PRINT_TOKENS print_token(stderr, &token); @@ -623,10 +615,10 @@ static inline void next_token(void) /** * Return the next token with a given lookahead. */ -static inline const token_t *look_ahead(int num) +static inline const token_t *look_ahead(size_t num) { - assert(num > 0 && num <= MAX_LOOKAHEAD); - int pos = (lookahead_bufpos+num-1) % MAX_LOOKAHEAD; + assert(0 < num && num <= MAX_LOOKAHEAD); + size_t pos = (lookahead_bufpos + num - 1) % MAX_LOOKAHEAD; return &lookahead_buffer[pos]; } @@ -757,7 +749,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) (assert(token.type == (token_type)), next_token()) /** * Report a parse error because an expected token was not found. @@ -977,13 +969,8 @@ static int get_akind_rank(atomic_type_kind_t akind) static int get_rank(const type_t *type) { assert(!is_typeref(type)); - /* The C-standard allows promoting enums to int or unsigned int (see § 7.2.2 - * and esp. footnote 108). However we can't fold constants (yet), so we - * can't decide whether unsigned int is possible, while int always works. - * (unsigned int would be preferable when possible... for stuff like - * struct { enum { ... } bla : 4; } ) */ if (type->kind == TYPE_ENUM) - return get_akind_rank(ATOMIC_TYPE_INT); + return get_akind_rank(type->enumt.akind); assert(type->kind == TYPE_ATOMIC); return get_akind_rank(type->atomic.akind); @@ -1473,35 +1460,13 @@ static void parse_gnu_attribute_model_arg(gnu_attribute_t *attribute) */ static void parse_gnu_attribute_mode_arg(gnu_attribute_t *attribute) { - /* TODO: find out what is allowed here... */ - - /* at least: byte, word, pointer, list of machine modes - * __XXX___ is interpreted as XXX */ add_anchor_token(')'); if (token.type != T_IDENTIFIER) { expect(T_IDENTIFIER, end_error); } - /* This isn't really correct, the backend should provide a list of machine - * specific modes (according to gcc philosophy that is...) */ - const char *symbol_str = token.v.symbol->string; - if (strcmp_underscore("QI", symbol_str) == 0 || - strcmp_underscore("byte", symbol_str) == 0) { - attribute->u.akind = ATOMIC_TYPE_CHAR; - } else if (strcmp_underscore("HI", symbol_str) == 0) { - attribute->u.akind = ATOMIC_TYPE_SHORT; - } else if (strcmp_underscore("SI", symbol_str) == 0 - || strcmp_underscore("word", symbol_str) == 0 - || strcmp_underscore("pointer", symbol_str) == 0) { - attribute->u.akind = ATOMIC_TYPE_INT; - } else if (strcmp_underscore("DI", symbol_str) == 0) { - attribute->u.akind = ATOMIC_TYPE_LONGLONG; - } else { - if (warning.other) - warningf(HERE, "ignoring unknown mode '%s'", symbol_str); - attribute->invalid = true; - } + attribute->u.symbol = token.v.symbol; next_token(); rem_anchor_token(')'); @@ -2282,6 +2247,7 @@ static initializer_t *initializer_from_expression(type_t *orig_type, return initializer_from_string(array_type, &expression->string.value); } + break; case EXPR_WIDE_STRING_LITERAL: { type_t *bare_wchar_type = skip_typeref(type_wchar_t); @@ -2289,6 +2255,7 @@ static initializer_t *initializer_from_expression(type_t *orig_type, return initializer_from_wide_string(array_type, &expression->wide_string.value); } + break; } default: @@ -2942,7 +2909,7 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env) result = parse_scalar_initializer(type, env->must_be_constant); } - /* § 6.7.8 (22) array initializers for arrays with unknown size determine + /* § 6.7.8:22 array initializers for arrays with unknown size determine * the array type size */ if (is_type_array(type) && type->array.size_expression == NULL && result != NULL) { @@ -3175,6 +3142,7 @@ static type_t *parse_enum_specifier(void) type_t *const type = allocate_type_zero(TYPE_ENUM); type->enumt.enume = &entity->enume; + type->enumt.akind = ATOMIC_TYPE_INT; if (token.type == '{') { if (symbol != NULL) { @@ -3289,13 +3257,7 @@ static type_t *create_builtin_type(symbol_t *const symbol, type_t *type = allocate_type_zero(TYPE_BUILTIN); type->builtin.symbol = symbol; type->builtin.real_type = real_type; - - type_t *result = typehash_insert(type); - if (type != result) { - free_type(type); - } - - return result; + return identify_new_type(type); } static type_t *get_typedef_type(symbol_t *symbol) @@ -3624,6 +3586,78 @@ static void finish_union_type(compound_type_t *type) type->base.alignment = alignment; } +static type_t *handle_attribute_mode(const gnu_attribute_t *attribute, + type_t *orig_type) +{ + type_t *type = skip_typeref(orig_type); + + /* at least: byte, word, pointer, list of machine modes + * __XXX___ is interpreted as XXX */ + + /* This isn't really correct, the backend should provide a list of machine + * specific modes (according to gcc philosophy that is...) */ + const char *symbol_str = attribute->u.symbol->string; + bool sign = is_type_signed(type); + atomic_type_kind_t akind; + if (strcmp_underscore("QI", symbol_str) == 0 || + strcmp_underscore("byte", symbol_str) == 0) { + akind = sign ? ATOMIC_TYPE_CHAR : ATOMIC_TYPE_UCHAR; + } else if (strcmp_underscore("HI", symbol_str) == 0) { + akind = sign ? ATOMIC_TYPE_SHORT : ATOMIC_TYPE_USHORT; + } else if (strcmp_underscore("SI", symbol_str) == 0 + || strcmp_underscore("word", symbol_str) == 0 + || strcmp_underscore("pointer", symbol_str) == 0) { + akind = sign ? ATOMIC_TYPE_INT : ATOMIC_TYPE_UINT; + } else if (strcmp_underscore("DI", symbol_str) == 0) { + akind = sign ? ATOMIC_TYPE_LONGLONG : ATOMIC_TYPE_ULONGLONG; + } else { + if (warning.other) + warningf(HERE, "ignoring unknown mode '%s'", symbol_str); + return orig_type; + } + + if (type->kind == TYPE_ATOMIC) { + type_t *copy = duplicate_type(type); + copy->atomic.akind = akind; + return identify_new_type(copy); + } else if (type->kind == TYPE_ENUM) { + type_t *copy = duplicate_type(type); + copy->enumt.akind = akind; + return identify_new_type(copy); + } else if (is_type_pointer(type)) { + warningf(HERE, "__attribute__((mode)) on pointers not implemented yet (ignored)"); + return type; + } + + errorf(HERE, "__attribute__((mode)) only allowed on integer, enum or pointer type"); + return orig_type; +} + +static type_t *handle_type_attributes(const gnu_attribute_t *attributes, + type_t *type) +{ + const gnu_attribute_t *attribute = attributes; + for ( ; attribute != NULL; attribute = attribute->next) { + if (attribute->invalid) + continue; + + if (attribute->kind == GNU_AK_MODE) { + type = handle_attribute_mode(attribute, type); + } else if (attribute->kind == GNU_AK_ALIGNED) { + int alignment = 32; /* TODO: fill in maximum useful alignment for + target machine */ + if (attribute->has_arguments) + alignment = attribute->u.argument; + + type_t *copy = duplicate_type(type); + copy->base.alignment = attribute->u.argument; + type = identify_new_type(copy); + } + } + + return type; +} + static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) { type_t *type = NULL; @@ -3639,8 +3673,6 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) while (true) { specifiers->modifiers |= parse_attributes(&specifiers->gnu_attributes); - if (specifiers->modifiers & DM_TRANSPARENT_UNION) - modifiers |= TYPE_MODIFIER_TRANSPARENT_UNION; switch (token.type) { /* storage class */ @@ -3861,6 +3893,9 @@ wrong_thread_stoarge_class: } finish_specifiers: + specifiers->modifiers + |= parse_attributes(&specifiers->gnu_attributes); + in_gcc_extension = old_gcc_extension; if (type == NULL || (saw_error && type_specifiers != 0)) { @@ -4049,15 +4084,19 @@ warn_about_long_long: /* FIXME: check type qualifiers here */ + if (specifiers->modifiers & DM_TRANSPARENT_UNION) + modifiers |= TYPE_MODIFIER_TRANSPARENT_UNION; type->base.qualifiers = qualifiers; type->base.modifiers = modifiers; - type_t *result = typehash_insert(type); - if (newtype && result != type) { - free_type(type); + if (newtype) { + type = identify_new_type(type); + } else { + type = typehash_insert(type); } - specifiers->type = result; + type = handle_type_attributes(specifiers->gnu_attributes, type); + specifiers->type = type; return; end_error: @@ -4557,47 +4596,22 @@ static void parse_declaration_attributes(entity_t *entity) if (type == NULL) return; - /* handle these strange/stupid mode attributes */ gnu_attribute_t *attribute = attributes; for ( ; attribute != NULL; attribute = attribute->next) { if (attribute->invalid) continue; if (attribute->kind == GNU_AK_MODE) { - atomic_type_kind_t akind = attribute->u.akind; - if (!is_type_signed(type)) { - switch (akind) { - case ATOMIC_TYPE_CHAR: akind = ATOMIC_TYPE_UCHAR; break; - case ATOMIC_TYPE_SHORT: akind = ATOMIC_TYPE_USHORT; break; - case ATOMIC_TYPE_INT: akind = ATOMIC_TYPE_UINT; break; - case ATOMIC_TYPE_LONGLONG: akind = ATOMIC_TYPE_ULONGLONG; break; - default: - panic("invalid akind in mode attribute"); - } - } else { - switch (akind) { - case ATOMIC_TYPE_CHAR: akind = ATOMIC_TYPE_SCHAR; break; - case ATOMIC_TYPE_SHORT: akind = ATOMIC_TYPE_SHORT; break; - case ATOMIC_TYPE_INT: akind = ATOMIC_TYPE_INT; break; - case ATOMIC_TYPE_LONGLONG: akind = ATOMIC_TYPE_LONGLONG; break; - default: - panic("invalid akind in mode attribute"); - } - } - type = make_atomic_type(akind, type->base.qualifiers); + type = handle_attribute_mode(attribute, type); } else if (attribute->kind == GNU_AK_ALIGNED) { int alignment = 32; /* TODO: fill in maximum usefull alignment for target machine */ if (attribute->has_arguments) alignment = attribute->u.argument; if (entity->kind == ENTITY_TYPEDEF) { - type_t *copy = duplicate_type(type); + type_t *copy = duplicate_type(type); copy->base.alignment = attribute->u.argument; - - type = typehash_insert(copy); - if (type != copy) { - obstack_free(type_obst, copy); - } + type = identify_new_type(copy); } else if(entity->kind == ENTITY_VARIABLE) { entity->variable.alignment = alignment; } else if(entity->kind == ENTITY_COMPOUND_MEMBER) { @@ -4611,13 +4625,9 @@ static void parse_declaration_attributes(entity_t *entity) type_modifiers |= TYPE_MODIFIER_TRANSPARENT_UNION; if (type->base.modifiers != type_modifiers) { - type_t *copy = duplicate_type(type); + type_t *copy = duplicate_type(type); copy->base.modifiers = type_modifiers; - - type = typehash_insert(copy); - if (type != copy) { - obstack_free(type_obst, copy); - } + type = identify_new_type(copy); } if (entity->kind == ENTITY_TYPEDEF) { @@ -4645,7 +4655,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_ function_type->function.return_type = type; type_t *skipped_return_type = skip_typeref(type); - /* §6.7.5.3(1) */ + /* §6.7.5.3:1 */ if (is_type_function(skipped_return_type)) { errorf(HERE, "function returning function is not allowed"); } else if (is_type_array(skipped_return_type)) { @@ -4707,7 +4717,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_ } type_t *skipped_type = skip_typeref(type); - /* §6.7.5.2(1) */ + /* §6.7.5.2:1 */ if (is_type_incomplete(skipped_type)) { errorf(HERE, "array of incomplete type '%T' is not allowed", type); } else if (is_type_function(skipped_type)) { @@ -4718,14 +4728,12 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_ } } - type_t *hashed_type = typehash_insert(type); - if (hashed_type != type) { - /* the function type was constructed earlier freeing it here will - * destroy other types... */ - if (iter->kind != CONSTRUCT_FUNCTION) { - free_type(type); - } - type = hashed_type; + /* The function type was constructed earlier. Freeing it here will + * destroy other types. */ + if (iter->kind == CONSTRUCT_FUNCTION) { + type = typehash_insert(type); + } else { + type = identify_new_type(type); } } @@ -5087,7 +5095,7 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition) type_t *const orig_type = decl->type; assert(orig_type != NULL); type_t *const type = skip_typeref(orig_type); - type_t * prev_type = skip_typeref(prev_decl->type); + type_t *const prev_type = skip_typeref(prev_decl->type); if (!types_compatible(type, prev_type)) { errorf(pos, @@ -5106,20 +5114,14 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition) prev_decl->type, symbol); } - unsigned new_storage_class = decl->storage_class; - if (is_type_incomplete(prev_type)) { - prev_decl->type = type; - prev_type = type; - } + storage_class_tag_t new_storage_class = decl->storage_class; /* pretend no storage class means extern for function * declarations (except if the previous declaration is neither * none nor extern) */ if (entity->kind == ENTITY_FUNCTION) { - if (prev_type->function.unspecified_parameters) { + if (prev_type->function.unspecified_parameters) prev_decl->type = type; - prev_type = type; - } switch (old_storage_class) { case STORAGE_CLASS_NONE: @@ -5142,6 +5144,8 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition) default: break; } + } else if (is_type_incomplete(prev_type)) { + prev_decl->type = type; } if (old_storage_class == STORAGE_CLASS_EXTERN && @@ -5288,7 +5292,7 @@ static void parse_init_declarator_rest(entity_t *entity) current_init_decl = NULL; if (entity->kind == ENTITY_VARIABLE) { - /* § 6.7.5 (22) array initializers for arrays with unknown size + /* § 6.7.5:22 array initializers for arrays with unknown size * determine the array type size */ declaration->type = env.type; entity->variable.initializer = initializer; @@ -5346,11 +5350,9 @@ static void check_variable_type_complete(entity_t *ent) if (!is_type_incomplete(type)) return; - /* GCC allows global arrays without size and assigns them a length of one, - * if no different declaration follows */ - if (is_type_array(type) && - c_mode & _GNUC && - ent->base.parent_scope == file_scope) { + /* §6.9.2:2 and §6.9.2:5: At the end of the translation incomplete arrays + * are given length one. */ + if (is_type_array(type) && ent->base.parent_scope == file_scope) { ARR_APP1(declaration_t*, incomplete_arrays, decl); return; } @@ -5555,12 +5557,9 @@ decl_list_end: new_type->function.parameters = parameters; new_type->function.unspecified_parameters = true; - type = typehash_insert(new_type); - if (type != new_type) { - obstack_free(type_obst, new_type); - } + new_type = identify_new_type(new_type); - entity->declaration.type = type; + entity->declaration.type = new_type; rem_anchor_token('{'); } @@ -6092,7 +6091,7 @@ found_break_parent: if (next == NULL) { noreturn_candidate = false; - type_t *const type = current_function->base.type; + type_t *const type = skip_typeref(current_function->base.type); assert(is_type_function(type)); type_t *const ret = skip_typeref(type->function.return_type); if (warning.return_type && @@ -6345,7 +6344,8 @@ static void parse_external_declaration(void) } assert(is_declaration(ndeclaration)); - type_t *type = skip_typeref(ndeclaration->declaration.type); + type_t *const orig_type = ndeclaration->declaration.type; + type_t * type = skip_typeref(orig_type); if (!is_type_function(type)) { if (is_type_valid(type)) { @@ -6354,6 +6354,11 @@ static void parse_external_declaration(void) } eat_block(); return; + } else if (is_typeref(orig_type)) { + /* §6.9.1:2 */ + errorf(&ndeclaration->base.source_position, + "type of function definition '%#T' is a typedef", + orig_type, ndeclaration->base.symbol); } if (warning.aggregate_return && @@ -6370,18 +6375,15 @@ static void parse_external_declaration(void) ndeclaration->base.symbol); } - /* § 6.7.5.3 (14) a function definition with () means no + /* § 6.7.5.3:14 a function definition with () means no * parameters (and not unspecified parameters) */ - if (type->function.unspecified_parameters - && type->function.parameters == NULL - && !type->function.kr_style_parameters) { - type_t *duplicate = duplicate_type(type); - duplicate->function.unspecified_parameters = false; + if (type->function.unspecified_parameters && + type->function.parameters == NULL && + !type->function.kr_style_parameters) { + type_t *copy = duplicate_type(type); + copy->function.unspecified_parameters = false; + type = identify_new_type(copy); - type = typehash_insert(duplicate); - if (type != duplicate) { - obstack_free(type_obst, duplicate); - } ndeclaration->declaration.type = type; } @@ -6822,11 +6824,7 @@ static entity_t *create_implicit_function(symbol_t *symbol, ntype->function.return_type = type_int; ntype->function.unspecified_parameters = true; ntype->function.linkage = LINKAGE_C; - - type_t *type = typehash_insert(ntype); - if (type != ntype) { - free_type(ntype); - } + type_t *type = identify_new_type(ntype); entity_t *entity = allocate_entity_zero(ENTITY_FUNCTION); entity->declaration.storage_class = STORAGE_CLASS_EXTERN; @@ -6866,12 +6864,7 @@ static type_t *make_function_2_type(type_t *return_type, type_t *argument_type1, type->function.return_type = return_type; type->function.parameters = parameter1; - type_t *result = typehash_insert(type); - if (result != type) { - free_type(type); - } - - return result; + return identify_new_type(type); } /** @@ -6892,12 +6885,7 @@ static type_t *make_function_1_type(type_t *return_type, type_t *argument_type) type->function.return_type = return_type; type->function.parameters = parameter; - type_t *result = typehash_insert(type); - if (result != type) { - free_type(type); - } - - return result; + return identify_new_type(type); } static type_t *make_function_0_type(type_t *return_type) @@ -6906,12 +6894,7 @@ static type_t *make_function_0_type(type_t *return_type) type->function.return_type = return_type; type->function.parameters = NULL; - type_t *result = typehash_insert(type); - if (result != type) { - free_type(type); - } - - return result; + return identify_new_type(type); } /** @@ -8559,7 +8542,7 @@ static bool check_pointer_arithmetic(const source_position_t *source_position, static bool is_lvalue(const expression_t *expression) { - /* TODO: doesn't seem to be consistent with §6.3.2.1 (1) */ + /* TODO: doesn't seem to be consistent with §6.3.2.1:1 */ switch (expression->kind) { case EXPR_ARRAY_ACCESS: case EXPR_COMPOUND_LITERAL: @@ -8885,7 +8868,8 @@ static void warn_div_by_zero(binary_expression_t const *const expression) /** * Check the semantic restrictions for a div/mod expression. */ -static void semantic_divmod_arithmetic(binary_expression_t *expression) { +static void semantic_divmod_arithmetic(binary_expression_t *expression) +{ semantic_binexpr_arithmetic(expression); warn_div_by_zero(expression); } @@ -10090,7 +10074,8 @@ end_error: * * @param statement the switch statement to check */ -static void check_enum_cases(const switch_statement_t *statement) { +static void check_enum_cases(const switch_statement_t *statement) +{ const type_t *type = skip_typeref(statement->expression->base.type); if (! is_type_enum(type)) return; @@ -11371,8 +11356,8 @@ translation_unit_t *finish_parsing(void) return result; } -/* GCC allows global arrays without size and assigns them a length of one, - * if no different declaration follows */ +/* §6.9.2:2 and §6.9.2:5: At the end of the translation incomplete arrays + * are given length one. */ static void complete_incomplete_arrays(void) { size_t n = ARR_LEN(incomplete_arrays); @@ -11395,9 +11380,7 @@ static void complete_incomplete_arrays(void) new_type->array.has_implicit_size = true; new_type->array.size = 1; - type_t *const result = typehash_insert(new_type); - if (type != result) - free_type(type); + type_t *const result = identify_new_type(new_type); decl->type = result; }