From 008105cca8fcc9d5bfe8c4431a43ace65b8dff1f Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Fri, 15 Feb 2008 10:59:57 +0000 Subject: [PATCH] fix string initializers, improve initializer semantic in parser [r18864] --- TODO | 1 + ast2firm.c | 30 +++++++++++++++++++++--------- parser.c | 43 +++++++++++++++++++++++++++++++++---------- 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/TODO b/TODO index 7bcd77b..53f83ed 100644 --- a/TODO +++ b/TODO @@ -29,6 +29,7 @@ Parser: them. - check semantic for functions declared/defined in global scope and declared again in a local scope +- print initialisation type_path for initializer errors ast2firm: - handle non-constant initializers diff --git a/ast2firm.c b/ast2firm.c index 1f81df3..6cc3300 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -2334,7 +2334,7 @@ static ir_node *compound_literal_to_firm( set_entity_variability(entity, variability_uninitialized); - /* create initialisation code TODO */ + /* create initialisation code */ initializer_t *initializer = expression->initializer; create_local_initializer(initializer, dbgi, entity, type); @@ -3177,15 +3177,21 @@ static ir_initializer_t *create_ir_initializer_list( } static ir_initializer_t *create_ir_initializer_string( - const initializer_string_t *initializer) + const initializer_string_t *initializer, type_t *type) { - size_t len = initializer->string.size; + size_t string_len = initializer->string.size; + assert(type->kind == TYPE_ARRAY && type->array.size_constant); + size_t len = type->array.size; ir_initializer_t *irinitializer = create_initializer_compound(len); const char *string = initializer->string.begin; ir_mode *mode = get_type_mode(ir_type_const_char); for(size_t i = 0; i < len; ++i) { + char c = 0; + if(i < string_len) + c = string[i]; + tarval *tv = new_tarval_from_long(string[i], mode); ir_initializer_t *char_initializer = create_initializer_tarval(tv); @@ -3196,15 +3202,21 @@ static ir_initializer_t *create_ir_initializer_string( } static ir_initializer_t *create_ir_initializer_wide_string( - const initializer_wide_string_t *initializer) + const initializer_wide_string_t *initializer, type_t *type) { - size_t len = initializer->string.size; + size_t string_len = initializer->string.size; + assert(type->kind == TYPE_ARRAY && type->array.size_constant); + size_t len = type->array.size; ir_initializer_t *irinitializer = create_initializer_compound(len); const wchar_rep_t *string = initializer->string.begin; ir_mode *mode = get_type_mode(ir_type_wchar_t); for(size_t i = 0; i < len; ++i) { + wchar_rep_t c = 0; + if(i < string_len) { + c = string[i]; + } tarval *tv = new_tarval_from_long(string[i], mode); ir_initializer_t *char_initializer = create_initializer_tarval(tv); @@ -3219,10 +3231,11 @@ static ir_initializer_t *create_ir_initializer( { switch(initializer->kind) { case INITIALIZER_STRING: - return create_ir_initializer_string(&initializer->string); + return create_ir_initializer_string(&initializer->string, type); case INITIALIZER_WIDE_STRING: - return create_ir_initializer_wide_string(&initializer->wide_string); + return create_ir_initializer_wide_string(&initializer->wide_string, + type); case INITIALIZER_LIST: return create_ir_initializer_list(&initializer->list, type); @@ -3526,8 +3539,6 @@ static void create_local_declaration(declaration_t *declaration) case STORAGE_CLASS_STATIC: create_local_static_variable(declaration); return; - case STORAGE_CLASS_ENUM_ENTRY: - panic("enum entry declaration in local block found"); case STORAGE_CLASS_EXTERN: create_global_variable(declaration); create_declaration_initializer(declaration); @@ -3545,6 +3556,7 @@ static void create_local_declaration(declaration_t *declaration) create_local_variable(declaration); } return; + case STORAGE_CLASS_ENUM_ENTRY: case STORAGE_CLASS_TYPEDEF: case STORAGE_CLASS_THREAD: case STORAGE_CLASS_THREAD_EXTERN: diff --git a/parser.c b/parser.c index fa554d1..f5e44b1 100644 --- a/parser.c +++ b/parser.c @@ -1003,7 +1003,8 @@ static initializer_t *initializer_from_expression(type_t *orig_type, return result; } -static initializer_t *parse_scalar_initializer(type_t *type) +static initializer_t *parse_scalar_initializer(type_t *type, + bool must_be_constant) { /* there might be extra {} hierarchies */ int braces = 0; @@ -1015,7 +1016,13 @@ static initializer_t *parse_scalar_initializer(type_t *type) braces++; } - expression_t *expression = parse_assignment_expression(); + expression_t *expression = parse_assignment_expression(); + if(must_be_constant && !is_constant_expression(expression)) { + errorf(expression->base.source_position, + "Initialisation expression '%E' is not constant\n", + expression); + } + initializer_t *initializer = initializer_from_expression(type, expression); if(initializer == NULL) { @@ -1304,7 +1311,7 @@ static void skip_initializers(void) } static initializer_t *parse_sub_initializer(type_path_t *path, - type_t *outer_type, size_t top_path_level) + type_t *outer_type, size_t top_path_level, bool must_be_constant) { type_t *orig_type = path->top_type; type_t *type = skip_typeref(orig_type); @@ -1340,12 +1347,13 @@ static initializer_t *parse_sub_initializer(type_path_t *path, if(token.type == '{') { if(is_type_scalar(type)) { - sub = parse_scalar_initializer(type); + sub = parse_scalar_initializer(type, must_be_constant); } else { eat('{'); descend_into_subtype(path); - sub = parse_sub_initializer(path, orig_type, top_path_level+1); + sub = parse_sub_initializer(path, orig_type, top_path_level+1, + must_be_constant); ascend_from_subtype(path); @@ -1355,6 +1363,12 @@ static initializer_t *parse_sub_initializer(type_path_t *path, /* must be an expression */ expression_t *expression = parse_assignment_expression(); + if(must_be_constant && !is_constant_expression(expression)) { + errorf(expression->base.source_position, + "Initialisation expression '%E' is not constant\n", + expression); + } + /* handle { "string" } special case */ if((expression->kind == EXPR_STRING_LITERAL || expression->kind == EXPR_WIDE_STRING_LITERAL) @@ -1431,7 +1445,8 @@ end_error: return NULL; } -static initializer_t *parse_initializer(type_t *const orig_type) +static initializer_t *parse_initializer(type_t *const orig_type, + bool must_be_constant) { initializer_t *result; @@ -1451,7 +1466,7 @@ static initializer_t *parse_initializer(type_t *const orig_type) if(is_type_scalar(type)) { /* TODO: § 6.7.8.11; eat {} without warning */ - result = parse_scalar_initializer(type); + result = parse_scalar_initializer(type, must_be_constant); if(token.type == ',') next_token(); @@ -1467,12 +1482,13 @@ static initializer_t *parse_initializer(type_t *const orig_type) descend_into_subtype(&path); - result = parse_sub_initializer(&path, orig_type, 1); + result = parse_sub_initializer(&path, orig_type, 1, must_be_constant); DEL_ARR_F(path.path); expect('}'); } else { + /* TODO: can this even happen? */ panic("TODO"); } @@ -2773,7 +2789,14 @@ static void parse_init_declarator_rest(declaration_t *declaration) parser_error_multiple_definition(declaration, token.source_position); } - initializer_t *initializer = parse_initializer(type); + bool must_be_constant = false; + if(declaration->storage_class == STORAGE_CLASS_STATIC + || declaration->storage_class == STORAGE_CLASS_THREAD_STATIC + || declaration->parent_scope == global_scope) { + must_be_constant = true; + } + + initializer_t *initializer = parse_initializer(type, must_be_constant); /* § 6.7.5 (22) array initializers for arrays with unknown size determine * the array type size */ @@ -3696,7 +3719,7 @@ static expression_t *parse_compound_literal(type_t *type) expression_t *expression = allocate_expression_zero(EXPR_COMPOUND_LITERAL); expression->compound_literal.type = type; - expression->compound_literal.initializer = parse_initializer(type); + expression->compound_literal.initializer = parse_initializer(type, false); expression->base.type = automatic_type_conversion(type); return expression; -- 2.20.1