From 402fd12785fd943aafd16df69089978e990e75ae Mon Sep 17 00:00:00 2001 From: Spoike Date: Thu, 14 May 2020 13:43:32 +0000 Subject: [PATCH] Fix uninitialised locals detection (for both -WF302 and -Olo). git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5693 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/qclib/initlib.c | 2 +- engine/qclib/qcc.h | 2 ++ engine/qclib/qcc_pr_comp.c | 25 +++++++++++++++---------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 260fe66fd..9638eea3a 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -1307,7 +1307,7 @@ void PR_RunGC (progfuncs_t *progfuncs) gc->tempstrings = (void*)((char*)gc->amem+prinst.addressableused); memcpy(gc->tempstrings, prinst.tempstrings, sizeof(*gc->tempstrings)*gc->maxtemps); - COM_AddWork(WG_LOADER, PR_QCGC_Thread, gc, NULL, 0, 0); + COM_InsertWork(WG_LOADER, PR_QCGC_Thread, gc, NULL, 0, 0); #ifdef GCTIMINGS endtime = Sys_DoubleTime(); diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index fa1be7d31..e4c2749c6 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -439,6 +439,7 @@ typedef struct QCC_def_s pbool nofold:1; pbool initialized:1; //true when a declaration included "= immediate". pbool isextern:1; //fteqw-specific lump entry + pbool isparameter:1; //its an engine parameter (thus preinitialised). int fromstatement; //statement that it is valid from. temp_t *temp; @@ -1013,6 +1014,7 @@ void QCC_PR_NewLine (pbool incomment); #define GDF_BASICTYPE 128 //don't care about #merge types not being known correctly. #define GDF_SCANLOCAL 256 //don't use the locals hash table #define GDF_POSTINIT 512 //field must be initialised at the end of the compile (allows arrays to be extended later) +#define GDF_PARAMETER 1024 QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, const char *name, struct QCC_function_s *scope, pbool allocate, int arraysize, unsigned int flags); QCC_sref_t QCC_PR_GetSRef (QCC_type_t *type, const char *name, struct QCC_function_s *scope, pbool allocate, int arraysize, unsigned int flags); void QCC_FreeTemp(QCC_sref_t t); diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 7a1c253ab..f10559897 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -233,6 +233,7 @@ QCC_statement_t *QCC_Generate_OP_IF(QCC_sref_t e, pbool preserve); QCC_statement_t *QCC_Generate_OP_GOTO(void); QCC_sref_t QCC_PR_GenerateLogicalNot(QCC_sref_t e, const char *errormessage); static QCC_function_t *QCC_PR_GenerateQCFunction (QCC_def_t *def, QCC_type_t *type, unsigned int *pif_flags); +static void QCC_StoreToSRef(QCC_sref_t dest, QCC_sref_t source, QCC_type_t *type, pbool preservesource, pbool preservedest); //NOTE: prints may use from the func argument's symbol, which can be awkward if its a temp. QCC_sref_t QCC_PR_GenerateFunctionCallSref (QCC_sref_t newself, QCC_sref_t func, QCC_sref_t *arglist, int argcount); @@ -5818,10 +5819,14 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func, if (args[i].ref.sym != d.sym || args[i].ref.ofs != d.ofs) { QCC_ForceUnFreeDef(d.sym); +#if 0 + QCC_StoreToSRef(d, args[i].ref, d.cast, false, false); +#else if (args[i].ref.cast->size == 3) QCC_FreeTemp(QCC_PR_StatementFlags (&pr_opcodes[OP_STORE_V], args[i].ref, d, NULL, 0)); else QCC_FreeTemp(QCC_PR_StatementFlags (&pr_opcodes[OP_STORE_F], args[i].ref, d, NULL, 0)); +#endif } else QCC_FreeTemp(args[i].ref); @@ -12530,7 +12535,7 @@ static pbool QCC_CheckUninitialised(int firststatement, int laststatement) continue; //not a real local, so will be properly initialised. if (local->symbolheader != local) continue; //ignore slave symbols, cos they're not interesting and should have been checked as part of the parent. - if (local->ofs < paramend) + if (local->isparameter) continue; err = QCC_CheckOneUninitialised(firststatement, laststatement, local, local->ofs, local->ofs + local->type->size * (local->arraysize?local->arraysize:1)); if (err > 0) @@ -13039,7 +13044,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ QCC_def_t *arg; for (u=0, p=0, arg=f->firstlocal ; unum_parms; u++, arg = arg->deftail->nextlocal) { - QCC_PR_DummyDef(type->params[u].type, pr_parm_names[u], pr_scope, 0, arg, 0, true, false); + QCC_PR_DummyDef(type->params[u].type, pr_parm_names[u], pr_scope, 0, arg, 0, true, GDF_PARAMETER); } if (type->vargcount) @@ -13047,7 +13052,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ if (!pr_parm_argcount_name) QCC_Error(ERR_INTERNAL, "I forgot what the va_count argument is meant to be called"); else - QCC_PR_DummyDef(type_float, pr_parm_argcount_name, pr_scope, 0, arg, 0, true, false); + QCC_PR_DummyDef(type_float, pr_parm_argcount_name, pr_scope, 0, arg, 0, true, 0); } } else @@ -13060,14 +13065,17 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ QC_snprintfz(pr_parm_names[u], sizeof(pr_parm_names[u]), "$arg_%u", u); QCC_PR_ParseWarning(WARN_PARAMWITHNONAME, "Parameter %u of %s is not named", u+1, pr_scope->name); } - parm = QCC_PR_GetSRef (type->params[u].type, pr_parm_names[u], pr_scope, 2, 0, false); + parm = QCC_PR_GetSRef (type->params[u].type, pr_parm_names[u], pr_scope, 2, 0, 0); parm.sym->used = true; //make sure system parameters get seen by the engine, even if the names are stripped.. parm.sym->referenced = true; for (o = 0; o < (type->params[u].type->size+2)/3; o++) { if (p < MAX_PARMS) + { + parm.sym->isparameter = true; parm.ofs+=3;//no need to copy anything, as the engine will do it for us. + } else { //extra parms need to be explicitly copied. if (!extra_parms[p - MAX_PARMS].sym) @@ -13859,6 +13867,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, const char *name, QCC_function_t *s def->scope = scope; def->constant = !!(flags & GDF_CONST); def->isstatic = !!(flags & GDF_STATIC); + def->isparameter = !!(flags & GDF_PARAMETER); if (arraysize && a < 0) { //array headers can be stripped safely. def->saved = false; @@ -15386,20 +15395,16 @@ void QCC_PR_ParseDefs (char *classname, pbool fatal) isstatic = true; else if (!pr_scope && QCC_PR_CheckKeyword(keyword_nonstatic, "nonstatic")) isstatic = false; - else if (QCC_PR_CheckKeyword(keyword_noref, "noref")) - noref=true; - else if (QCC_PR_CheckKeyword(keyword_unused, "unused")) + else if (QCC_PR_CheckKeyword(keyword_unused, "unused") || QCC_PR_CheckKeyword(keyword_noref, "noref")) noref=true; else if (QCC_PR_CheckKeyword(keyword_used, "used")) forceused=true; else if (QCC_PR_CheckKeyword(keyword_nosave, "nosave")) nosave = true; - else if (QCC_PR_CheckKeyword(keyword_strip, "strip")) + else if (QCC_PR_CheckKeyword(keyword_strip, "strip") || QCC_PR_CheckKeyword(keyword_ignore, "ignore")) dostrip = true; else if (QCC_PR_CheckKeyword(keyword_inline, "inline")) allowinline = true; - else if (QCC_PR_CheckKeyword(keyword_ignore, "ignore")) - dostrip = true; else if (QCC_PR_CheckKeyword(keyword_wrap, "wrap")) dowrap = true; else if (QCC_PR_CheckKeyword(keyword_weak, "weak"))