diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index e63e077f4..f21d2e4cb 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -43,6 +43,7 @@ typedef struct def_s { struct reloc_s *refs; // for relocations unsigned initialized:1; // for uninit var detection + unsigned set:1; // uninit var auto-inited unsigned constant:1; // 1 when a declaration included "= immediate" unsigned freed:1; // already freed from the scope unsigned removed:1; // already removed from the symbol table diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index d3ed1b0ac..2ef0cb98b 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -46,6 +46,7 @@ typedef struct function_s { struct def_s *def; struct scope_s *scope; struct reloc_s *refs; + struct expr_s *var_init; } function_t; extern function_t *current_func; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 8177a7e38..5dd4815e3 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -291,15 +291,26 @@ type_mismatch (expr_t *e1, expr_t *e2, int op) static void check_initialized (expr_t *e) { - if (options.warnings.uninited_variable) { - if (e->type == ex_def - && !(e->e.def->type->type == ev_func - && e->e.def->global) - && !(e->e.def->type->type == ev_struct) - && !e->e.def->external - && !e->e.def->initialized) { - warning (e, "%s may be used uninitialized", e->e.def->name); - e->e.def->initialized = 1; // only warn once + const char *name; + + if (e->type == ex_def + && !(e->e.def->type->type == ev_func + && e->e.def->global) + && !(e->e.def->type->type == ev_struct) + && !e->e.def->external + && !e->e.def->initialized) { + name = e->e.def->name; + if (options.warnings.uninited_variable) + warning (e, "%s may be used uninitialized", name); + e->e.def->initialized = 1; // only warn once + if (options.traditional && !e->e.def->set) { + e->e.def->set = 1; // only auto-init once + e = assign_expr (e, new_nil_expr ()); + e->file = current_func->s_file; + e->line = current_func->def->line; + e->next = current_func->var_init; + current_func->var_init = e; + notice (e, "auto-initializing %s", name); } } } diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 3727b1c02..296461edb 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -274,6 +274,11 @@ emit_function (function_t *f, expr_t *e) if (f->aux) lineno_base = f->aux->source_line; + while (f->var_init) { + emit_expr (f->var_init); + f->var_init = f->var_init->next; + } + current_scope = f->scope; while (e) { //printf ("%d ", pr.source_line); diff --git a/tools/qfcc/source/idstuff.c b/tools/qfcc/source/idstuff.c index 7c97d8620..a6f935150 100644 --- a/tools/qfcc/source/idstuff.c +++ b/tools/qfcc/source/idstuff.c @@ -225,7 +225,7 @@ WriteProgdefs (const char *filename) RESERVED_OFS); for (d = pr.scope->head; d; d = d->def_next) { - if (!strcmp (d->name, "end_sys_globals")) + if (d->name && !strcmp (d->name, "end_sys_globals")) break; if (!d->ofs) continue; @@ -259,10 +259,10 @@ WriteProgdefs (const char *filename) // print all fields fprintf (f, "typedef struct\n{\n"); for (d = pr.scope->head; d; d = d->def_next) { - if (!strcmp (d->name, "end_sys_fields")) + if (d->name && !strcmp (d->name, "end_sys_fields")) break; - if (!d->ofs || d->type->type != ev_field) + if (!d->name || !d->ofs || d->type->type != ev_field) continue; switch (d->type->aux_type->type) {