diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index b9f805526..c7535b5ff 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -91,6 +91,8 @@ hashtab_t *save_local_inits (scope_t *scope); hashtab_t *merge_local_inits (hashtab_t *dl_1, hashtab_t *dl_2); void restore_local_inits (hashtab_t *def_list); void free_local_inits (hashtab_t *def_list); +static def_t *create_def (type_t *type, const char *name, scope_t *scope, + storage_class_t storage); expr_t *argc_expr (void); expr_t *argv_expr (void); @@ -169,7 +171,7 @@ expr_t *argv_expr (void); %type fdef_name cfunction_def func_def %type function_decl %type param param_list -%type def_name opt_initializer methoddef var_initializer +%type opt_initializer methoddef var_initializer %type const opt_expr fexpr expr element_list element_list1 element %type string_val opt_state_expr think opt_step array_decl %type statement statements statement_block @@ -178,7 +180,7 @@ expr_t *argv_expr (void); %type begin_function builtin_function %type save_inits %type switch_block -%type identifier +%type def_name identifier %type selector reserved_word %type optparmlist unaryselector keyworddecl keywordselector @@ -476,9 +478,9 @@ def_list def_item : def_name opt_initializer { - if ($1 && !$1->local - && $1->type->type != ev_func) - def_initialized ($1); + if ($2 && !$2->local + && $2->type->type != ev_func) + def_initialized ($2); } ; @@ -556,60 +558,51 @@ code_func ; def_name - : identifier - { - scope_type st = current_scope->type; - // traditional functions have only the one scope - //FIXME should the scope be set to local when the params scope - //is created in traditional mode? - if (options.traditional && st == sc_params) - st = sc_local; - if (st == sc_local) { - def_t *def = get_def (0, $1, current_scope, st_none); - if (def) { - if (def->scope->type == sc_params - && current_scope->parent->type == sc_params) { - warning (0, "local %s shadows param %s", $1, - def->name); - } - if (def->scope == current_scope) { - expr_t e; - warning (0, "local %s redeclared", $1); - e.file = def->file; - e.line = def->line; - warning (&e, "previously declared here"); - } - } - } - $$ = get_def ($0, $1, current_scope, current_storage); - } + : identifier { $$ = $1; } ; opt_initializer - : /*empty*/ { } - | { $$ = $0; } - var_initializer { (void) ($1); } + : /*empty*/ + { + $$ = create_def ($-1, $0, current_scope, + current_storage); + } + | var_initializer { $$ = $1; } ; var_initializer : '=' expr // don't bother folding twice { - if (current_scope->type == sc_local - || current_scope->type == sc_params) { - expr_t *expr = assign_expr (new_def_expr ($0), $2); + int local = 0; + const char *name = $0; + type_t *type = $-1; + + if (current_scope->type == sc_params) { + local = 0; + $$ = create_def (type, name, current_scope, st_static); + printf ("params\n"); + } else { + local = current_scope->type == sc_local; + $$ = create_def (type, name, current_scope, current_storage); + printf ("%s\n", local ? "local" : "static/global"); + } + if (local) { + expr_t *expr = assign_expr (new_def_expr ($$), $2); expr = fold_constants (expr); append_expr (local_expr, expr); - def_initialized ($0); + def_initialized ($$); + printf (" local\n"); } else { + printf (" non-local\n"); $2 = constant_expr ($2); if ($2->type >= ex_string) { - if ($0->constant) { - error ($2, "%s re-initialized", $0->name); + if ($$->constant) { + error ($2, "%s re-initialized", $$->name); } else { - if ($0->type->type == ev_func) { + if ($$->type->type == ev_func) { PARSE_ERROR; } else { - ReuseConstant ($2, $0); + ReuseConstant ($2, $$); } } } else { @@ -619,7 +612,9 @@ var_initializer } | '=' '{' { current_init = new_block_expr (); } element_list '}' { - init_elements ($0, $4); + $$ = create_def ($-1, $0, current_scope, + current_storage); + init_elements ($$, $4); current_init = 0; } ; @@ -654,9 +649,10 @@ opt_state_expr ; think - : { $$ = &type_function; } def_name + : def_name { - $$ = new_def_expr ($2); + $$ = new_def_expr (create_def (&type_function, $1, current_scope, + current_storage)); (void) ($1); } | '(' fexpr ')' @@ -1698,6 +1694,36 @@ scan_scope (hashtab_t *tab, scope_t *scope) } } +static def_t * +create_def (type_t *type, const char *name, scope_t *scope, + storage_class_t storage) +{ + scope_type st = scope->type; + // traditional functions have only the one scope + //FIXME should the scope be set to local when the params scope + //is created in traditional mode? + if (options.traditional && st == sc_params) + st = sc_local; + if (st == sc_local) { + def_t *def = get_def (0, name, scope, st_none); + if (def) { + if (def->scope->type == sc_params + && scope->parent->type == sc_params) { + warning (0, "local %s shadows param %s", name, + def->name); + } + if (def->scope == scope) { + expr_t e; + warning (0, "local %s redeclared", name); + e.file = def->file; + e.line = def->line; + warning (&e, "previously declared here"); + } + } + } + return get_def (type, name, scope, storage); +} + hashtab_t * save_local_inits (scope_t *scope) {