diff --git a/tools/qfcc/TODO b/tools/qfcc/TODO index 8206b2e14..aef6a595c 100644 --- a/tools/qfcc/TODO +++ b/tools/qfcc/TODO @@ -17,5 +17,6 @@ o switch/case, for any type o break/continue keywords for switch() and for(;;) o quaternion type. Tricky: requires 4 word args/return o CSE optimisations -o full scoping +X full scoping o short circuit logic for && and || (optional?) +o warn for local shaddowing parameter diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 189b58e61..fcd378100 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -285,12 +285,14 @@ typedef struct statref_s { typedef struct def_s { type_t *type; const char *name; - int num_locals; + int locals; + int *alloc; gofs_t ofs; int initialized; // for uninit var detection int constant; // 1 when a declaration included "= immediate" statref_t *refs; // for relocations + int removed; // already removed from the symbol table int used; // unused local detection string_t file; // source file int line; // source line diff --git a/tools/qfcc/source/pr_def.c b/tools/qfcc/source/pr_def.c index 216703266..6d2fbfe4d 100644 --- a/tools/qfcc/source/pr_def.c +++ b/tools/qfcc/source/pr_def.c @@ -218,8 +218,8 @@ PR_GetTempDef (type_t *type, def_t *scope) def->type = type; } else { def = PR_NewDef (type, 0, scope); - def->ofs = scope->num_locals; - scope->num_locals += type_size[size]; + def->ofs = *scope->alloc; + *scope->alloc += type_size[size]; } def->users = 0; def->next = temp_scope.next; @@ -279,7 +279,10 @@ PR_FlushScope (def_t *scope, int force_used) e.file = def->file; warning (&e, "unused variable `%s'", def->name); } - Hash_Del (defs_by_name, def->name); + if (!def->removed) { + Hash_Del (defs_by_name, def->name); + def->removed = 1; + } } } } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 7ab9d7eb3..cc4f5fbfe 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -179,6 +179,8 @@ maybe_func $$.type = current_type; $$.pscope = param_scope.scope_next; param_scope.scope_next = 0; + param_scope.alloc = ¶m_scope.locals; + *param_scope.alloc = 0; pr_scope = ¶m_scope; } param_list @@ -220,7 +222,7 @@ def_item def_name : NAME { - $$ = PR_GetDef (current_type, $1, pr_scope, pr_scope ? &pr_scope->num_locals : &numpr_globals); + $$ = PR_GetDef (current_type, $1, pr_scope, pr_scope ? pr_scope->alloc : &numpr_globals); current_def = $$; } ; @@ -353,9 +355,28 @@ end_function ; statement_block - : '{' statements '}' + : '{' { - $$ = $2; + def_t *scope = PR_NewDef (&type_void, ".scope", pr_scope); + scope->alloc = pr_scope->alloc; + scope->used = 1; + pr_scope->scope_next = scope->scope_next; + scope->scope_next = 0; + pr_scope = scope; + } + statements '}' + { + def_t *scope = pr_scope; + + PR_FlushScope (pr_scope, 1); + + while (scope->scope_next) + scope = scope->scope_next; + + scope->scope_next = pr_scope->scope->scope_next; + pr_scope->scope->scope_next = pr_scope; + pr_scope = pr_scope->scope; + $$ = $3; } ; @@ -656,8 +677,10 @@ build_scope (function_t *f, def_t *func) def_t *def; type_t *ftype = func->type; + func->alloc = &func->locals; + for (i = 0; i < ftype->num_parms; i++) { - def = PR_GetDef (ftype->parm_types[i], pr_parm_names[i], func, &func->num_locals); + def = PR_GetDef (ftype->parm_types[i], pr_parm_names[i], func, func->alloc); f->parm_ofs[i] = def->ofs; if (i > 0 && f->parm_ofs[i] < f->parm_ofs[i - 1]) Error ("bad parm order"); @@ -705,7 +728,7 @@ finish_function (function_t *f) df->s_name = ReuseString (f->def->name); df->s_file = s_file; df->numparms = f->def->type->num_parms; - df->locals = f->def->num_locals; + df->locals = f->def->locals; df->parm_start = 0; for (i = 0; i < df->numparms; i++) df->parm_size[i] = type_size[f->def->type->parm_types[i]->type]; diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 221d95261..c9c955d60 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -738,8 +738,8 @@ PR_FinishCompilation (void) for (f = pr_functions; f; f = f->next) { if (f->builtin) continue; - if (f->def->num_locals > num_localdefs) { - num_localdefs = f->def->num_locals; + if (f->def->locals > num_localdefs) { + num_localdefs = f->def->locals; big_function = f->def->name; } f->dfunc->parm_start = numpr_globals;