From 093437bbb2c7dfc77f0c139b11ea4c6b779212b1 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Thu, 6 Mar 2008 13:40:53 +0000 Subject: [PATCH] More fixes for initializers: - generate warnings/errors for superflous initializers - do NOT put them into the initializer list or Firm will crash .., - allow empty initializers [r18913] --- parser.c | 182 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 121 insertions(+), 61 deletions(-) diff --git a/parser.c b/parser.c index 764a0e1..a951117 100644 --- a/parser.c +++ b/parser.c @@ -57,12 +57,14 @@ struct declaration_specifiers_t { type_t *type; }; +/** + * An environment for parsing initializers (and compound literals). + */ typedef struct parse_initializer_env_t { type_t *type; /**< the type of the initializer. In case of an array type with unspecified size this gets adjusted to the actual size. */ - initializer_t *initializer; /**< initializer will be filled in here */ - declaration_t *declaration; /**< the declaration that is initialized */ + declaration_t *declaration; /**< the declaration that is initialized if any */ bool must_be_constant; } parse_initializer_env_t; @@ -988,6 +990,9 @@ static initializer_t *initializer_from_wide_string(array_type_t *const type, return initializer; } +/** + * Build an initializer from a given expression. + */ static initializer_t *initializer_from_expression(type_t *orig_type, expression_t *expression) { @@ -1098,40 +1103,43 @@ static initializer_t *parse_scalar_initializer(type_t *type, return initializer; } +/** + * An entry in the type path. + */ typedef struct type_path_entry_t type_path_entry_t; struct type_path_entry_t { - type_t *type; + type_t *type; /**< the upper top type. restored to path->top_tye if this entry is popped. */ union { - size_t index; - declaration_t *compound_entry; + size_t index; /**< For array types: the current index. */ + declaration_t *compound_entry; /**< For compound types: the current declaration. */ } v; }; +/** + * A type path expression a position inside compound or array types. + */ typedef struct type_path_t type_path_t; struct type_path_t { - type_path_entry_t *path; + type_path_entry_t *path; /**< An flexible array containing the current path. */ type_t *top_type; /**< type of the element the path points */ size_t max_index; /**< largest index in outermost array */ - bool invalid; }; +/** + * Prints a type path for debugging. + */ static __attribute__((unused)) void debug_print_type_path( const type_path_t *path) { size_t len = ARR_LEN(path->path); - if(path->invalid) { - fprintf(stderr, "invalid path"); - return; - } - for(size_t i = 0; i < len; ++i) { const type_path_entry_t *entry = & path->path[i]; type_t *type = skip_typeref(entry->type); if(is_type_compound(type)) { /* in gcc mode structs can have no members */ - if(entry->v.compound_entry->symbol->string) { + if(entry->v.compound_entry == NULL) { assert(i == len-1); continue; } @@ -1142,20 +1150,27 @@ static __attribute__((unused)) void debug_print_type_path( fprintf(stderr, "-INVALID-"); } } - if (path->top_type != NULL) { + if(path->top_type != NULL) { fprintf(stderr, " ("); print_type(path->top_type); fprintf(stderr, ")"); } } +/** + * Return the top type path entry, ie. in a path + * (type).a.b returns the b. + */ static type_path_entry_t *get_type_path_top(const type_path_t *path) { size_t len = ARR_LEN(path->path); assert(len > 0); - return & path->path[len-1]; + return &path->path[len-1]; } +/** + * Enlarge the type path by an (empty) element. + */ static type_path_entry_t *append_to_type_path(type_path_t *path) { size_t len = ARR_LEN(path->path); @@ -1166,6 +1181,10 @@ static type_path_entry_t *append_to_type_path(type_path_t *path) return result; } +/** + * Descending into a sub-type. Enter the scope of the current + * top_type. + */ static void descend_into_subtype(type_path_t *path) { type_t *orig_top_type = path->top_type; @@ -1179,13 +1198,12 @@ static void descend_into_subtype(type_path_t *path) if(is_type_compound(top_type)) { declaration_t *declaration = top_type->compound.declaration; declaration_t *entry = declaration->scope.declarations; + top->v.compound_entry = entry; if(entry != NULL) { - top->v.compound_entry = entry; - path->top_type = entry->type; + path->top_type = entry->type; } else { - top->v.compound_entry = NULL; - path->top_type = NULL; + path->top_type = NULL; } } else { assert(is_type_array(top_type)); @@ -1195,6 +1213,10 @@ static void descend_into_subtype(type_path_t *path) } } +/** + * Pop an entry from the given type path, ie. returning from + * (type).a.b to (type).a + */ static void ascend_from_subtype(type_path_t *path) { type_path_entry_t *top = get_type_path_top(path); @@ -1205,10 +1227,13 @@ static void ascend_from_subtype(type_path_t *path) ARR_RESIZE(type_path_entry_t, path->path, len-1); } +/** + * Pop entries from the given type path until the given + * path level is reached. + */ static void ascend_to(type_path_t *path, size_t top_path_level) { size_t len = ARR_LEN(path->path); - assert(len >= top_path_level); while(len > top_path_level) { ascend_from_subtype(path); @@ -1305,8 +1330,6 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, descend_into_subtype(path); } } - - path->invalid = false; return true; failed: @@ -1315,9 +1338,6 @@ failed: static void advance_current_object(type_path_t *path, size_t top_path_level) { - if(path->invalid) - return; - type_path_entry_t *top = get_type_path_top(path); type_t *type = skip_typeref(top->type); @@ -1351,10 +1371,13 @@ static void advance_current_object(type_path_t *path, size_t top_path_level) ascend_from_subtype(path); advance_current_object(path, top_path_level); } else { - path->invalid = true; + path->top_type = NULL; } } +/** + * skip any {...} blocks until a closing braket is reached. + */ static void skip_initializers(void) { if(token.type == '{') @@ -1371,31 +1394,32 @@ static void skip_initializers(void) } } +/** + * Parse a part of an initialiser for a struct or union, + */ static initializer_t *parse_sub_initializer(type_path_t *path, type_t *outer_type, size_t top_path_level, parse_initializer_env_t *env) { - type_t *orig_type = path->top_type; - - if(orig_type == NULL) { - /* We don't have declarations in this scope. Issue an error and skip - * initializers in this case. */ - if (env->declaration != NULL) - warningf(HERE, "excess elements in struct initializer for '%Y'", - env->declaration->symbol); - else - warningf(HERE, "excess elements in struct initializer"); - skip_initializers(); + if(token.type == '}') { + /* empty initializer */ return NULL; } - type_t *type = skip_typeref(orig_type); + type_t *orig_type = path->top_type; + type_t *type = NULL; - /* we can't do usefull stuff if we didn't even parse the type. Skip the - * initializers in this case. */ - if(!is_type_valid(type)) { - skip_initializers(); - return NULL; + if (orig_type == NULL) { + /* We are initializing an empty compound. */ + } else { + type = skip_typeref(orig_type); + + /* we can't do usefull stuff if we didn't even parse the type. Skip the + * initializers in this case. */ + if(!is_type_valid(type)) { + skip_initializers(); + return NULL; + } } initializer_t **initializers = NEW_ARR_F(initializer_t*, 0); @@ -1421,18 +1445,29 @@ static initializer_t *parse_sub_initializer(type_path_t *path, initializer_t *sub; if(token.type == '{') { - if(is_type_scalar(type)) { + if(type != NULL && is_type_scalar(type)) { sub = parse_scalar_initializer(type, env->must_be_constant); } else { eat('{'); - descend_into_subtype(path); + if(type == NULL) { + if (env->declaration != NULL) + errorf(HERE, "extra brace group at end of initializer for '%Y'", + env->declaration->symbol); + else + errorf(HERE, "extra brace group at end of initializer"); + } else + descend_into_subtype(path); sub = parse_sub_initializer(path, orig_type, top_path_level+1, env); - ascend_from_subtype(path); - - expect_block('}'); + if(type != NULL) { + ascend_from_subtype(path); + expect_block('}'); + } else { + expect_block('}'); + goto error_parse_next; + } } } else { /* must be an expression */ @@ -1444,6 +1479,11 @@ static initializer_t *parse_sub_initializer(type_path_t *path, expression); } + if(type == NULL) { + /* we are already outside, ... */ + goto error_excess; + } + /* handle { "string" } special case */ if((expression->kind == EXPR_STRING_LITERAL || expression->kind == EXPR_WIDE_STRING_LITERAL) @@ -1495,9 +1535,19 @@ static initializer_t *parse_sub_initializer(type_path_t *path, path->max_index = index; } - /* append to initializers list */ - ARR_APP1(initializer_t*, initializers, sub); + if(type != NULL) { + /* append to initializers list */ + ARR_APP1(initializer_t*, initializers, sub); + } else { +error_excess: + if(env->declaration != NULL) + warningf(HERE, "excess elements in struct initializer for '%Y'", + env->declaration->symbol); + else + warningf(HERE, "excess elements in struct initializer"); + } +error_parse_next: if(token.type == '}') { break; } @@ -1506,9 +1556,15 @@ static initializer_t *parse_sub_initializer(type_path_t *path, break; } - advance_current_object(path, top_path_level); - orig_type = path->top_type; - type = skip_typeref(orig_type); + if(type != NULL) { + /* advance to the next declaration if we are not at the end */ + advance_current_object(path, top_path_level); + orig_type = path->top_type; + if(orig_type != NULL) + type = skip_typeref(orig_type); + else + type = NULL; + } } size_t len = ARR_LEN(initializers); @@ -1531,9 +1587,10 @@ end_error: } /** - * Parses an initializer. + * Parses an initializer. Parsers either a compound literal + * (env->declaration == NULL) or an initializer of a declaration. */ -static void parse_initializer(parse_initializer_env_t *env) +static initializer_t *parse_initializer(parse_initializer_env_t *env) { type_t *type = skip_typeref(env->type); initializer_t *result = NULL; @@ -1558,7 +1615,7 @@ static void parse_initializer(parse_initializer_env_t *env) expect('}'); } else { - /* parse_scalar_initializer also works in this case: we simply + /* parse_scalar_initializer() also works in this case: we simply * have an expression without {} around it */ result = parse_scalar_initializer(type, env->must_be_constant); } @@ -1597,7 +1654,9 @@ static void parse_initializer(parse_initializer_env_t *env) env->type = new_type; } - env->initializer = result; + return result; +end_error: + return NULL; end_error: ; @@ -2933,7 +2992,8 @@ static void parse_init_declarator_rest(declaration_t *declaration) env.type = orig_type; env.must_be_constant = must_be_constant; env.declaration = declaration; - parse_initializer(&env); + + initializer_t *initializer = parse_initializer(&env); if(env.type != orig_type) { orig_type = env.type; @@ -2946,7 +3006,7 @@ static void parse_init_declarator_rest(declaration_t *declaration) "initializers not allowed for function types at declator '%Y' (type '%T')", declaration->symbol, orig_type); } else { - declaration->init.initializer = env.initializer; + declaration->init.initializer = initializer; } } @@ -3875,11 +3935,11 @@ static expression_t *parse_compound_literal(type_t *type) env.type = type; env.declaration = NULL; env.must_be_constant = false; - parse_initializer(&env); + initializer_t *initializer = parse_initializer(&env); type = env.type; + expression->compound_literal.initializer = initializer; expression->compound_literal.type = type; - expression->compound_literal.initializer = env.initializer; expression->base.type = automatic_type_conversion(type); return expression; -- 2.20.1