diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index 0b8177abf..23c8697ce 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -601,7 +601,8 @@ pbool LocateDebugTerm(progfuncs_t *progfuncs, char *key, eval_t **result, etype_ { ddef32_t *def; fdef_t *fdef; - eval_t *val = NULL; + int fofs; + eval_t *val = NULL, *fval=NULL; char *c, *c2; etype_t type = ev_void; struct edictrun_s *ed; @@ -653,14 +654,28 @@ pbool LocateDebugTerm(progfuncs_t *progfuncs, char *key, eval_t **result, etype_ if (type != ev_entity) return false; if (c)*c = '\0'; - fdef = ED_FindField(progfuncs, COM_TrimString(c2)); - if (c)*c = '.'; - if (!fdef) - return false; + + c2 = COM_TrimString(c2); + def = ED_FindLocalOrGlobal(progfuncs, c2, &fval); + if (def) + { + fofs = fval->_int + progfuncs->funcs.fieldadjust; + } + else + { + fdef = ED_FindField(progfuncs, c2); + if (c)*c = '.'; + if (!fdef) + return false; + fofs = fdef->ofs; + } + ed = PROG_TO_EDICT(progfuncs, val->_int); if (!ed) return false; - val = (eval_t *) (((char *)ed->fields) + fdef->ofs*4); + if (fofs < 0 || fofs >= max_fields_size) + return false; + val = (eval_t *) (((char *)ed->fields) + fofs*4); type = fdef->type; } *rettype = type; diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index 43650f7cd..58bd6a957 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -647,8 +647,10 @@ enum { WARN_MISSINGOPTIONAL, WARN_SYSTEMCRC, WARN_CONDITIONALTYPEMISMATCH, - WARN_SELFNOTTHIS, //warned for because 'self' does not have the right type. we convert such references to 'this' instead, which is more usable. - WARN_EVILPREPROCESSOR, //exploited by nexuiz, and generally unsafe. + WARN_SELFNOTTHIS, //warned for because 'self' does not have the right type. we convert such references to 'this' instead, which is more usable. + WARN_EVILPREPROCESSOR, //exploited by nexuiz, and generally unsafe. + WARN_UNARYNOTSCOPE, //!foo & bar the ! applies to the result of &. This is unlike C. + WARN_STRICTTYPEMISMATCH, //self.think = T_Damage; both are functions, but the arguments/return types/etc differ. ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called. diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 70856c0e3..7a17d4258 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -509,8 +509,8 @@ QCC_opcode_t pr_opcodes[] = {7, "", "SWITCH_I", -1, ASSOC_LEFT, &type_void, NULL, &type_void}, {7, "<>", "GLOAD_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{6, "", "IF_F", -1, ASSOC_RIGHT, &type_float, NULL, &type_void}, -{6, "","IFNOT_F", -1, ASSOC_RIGHT, &type_float, NULL, &type_void}, +{7, "", "IF_F", -1, ASSOC_RIGHT, &type_float, NULL, &type_void}, +{7, "","IFNOT_F", -1, ASSOC_RIGHT, &type_float, NULL, &type_void}, /* emulated ops begin here */ {7, "<>", "OP_EMULATED", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, @@ -587,7 +587,7 @@ pbool OpAssignsToC(unsigned int op) if(op == OP_STOREP_C || op == OP_LOADP_C) return false; if(op >= OP_MULSTORE_F && op <= OP_SUBSTOREP_V) - return false; + return false; //actually they do. return true; } pbool OpAssignsToB(unsigned int op) @@ -1949,7 +1949,7 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ { TypeName(var_a->type, typea, sizeof(typea)); TypeName(var_b->type, typeb, sizeof(typeb)); - QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Implicit assignment from %s to %s %s", typea, typeb, var_b->name); + QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "Implicit assignment from %s to %s %s", typea, typeb, var_b->name); } } break; @@ -1974,7 +1974,7 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ { TypeName(var_a->type, typea, sizeof(typea)); TypeName(var_b->type->aux_type, typeb, sizeof(typeb)); - QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Implicit field assignment from %s to %s", typea, typeb); + QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "Implicit field assignment from %s to %s", typea, typeb); } } break; @@ -2022,7 +2022,7 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ { TypeName(var_a->type, typea, sizeof(typea)); TypeName(var_b->type, typeb, sizeof(typeb)); - QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "'%s' type mismatch: %s with %s", op->name, typea, typeb); + QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "'%s' type mismatch: %s with %s", op->name, typea, typeb); } if ((var_a->constant && var_b->constant && !var_a->temp && !var_b->temp) || var_a->ofs == var_b->ofs) QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant"); @@ -5937,7 +5937,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) e->type = e2->type->aux_type; if (priority > 1 && exprflags & EXPR_WARN_ABOVE_1) - QCC_PR_ParseWarning(0, "You may wish to add brackets after that ! operator"); + QCC_PR_ParseWarning(WARN_UNARYNOTSCOPE, "You may wish to add brackets after that ! operator"); break; } @@ -8062,7 +8062,7 @@ void QCC_WriteAsmFunction(QCC_def_t *sc, unsigned int firststatement, gofs_t fir } else fprintf(asmfile, ",\t%i", statements[i].b); - if (pr_opcodes[statements[i].op].type_c != &type_void && pr_opcodes[statements[i].op].associative==ASSOC_LEFT) + if (pr_opcodes[statements[i].op].type_c != &type_void) && (pr_opcodes[statements[i].op].associative==ASSOC_LEFT || statements[i].c)) { if (pr_opcodes[statements[i].op].type_c) { @@ -9090,7 +9090,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool def = QCC_PR_GetDef(NULL, name, NULL, false, arraysize, false); if (def) { - QCC_PR_ParseWarning(WARN_SAMENAMEASGLOBAL, "Local \"%s\" defined with name of a global", name); + QCC_PR_ParseWarning(WARN_SAMENAMEASGLOBAL, "Local \"%s\" hides global with same name", name); QCC_PR_ParsePrintDef(WARN_SAMENAMEASGLOBAL, def); } } @@ -9209,6 +9209,7 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, case ev_pointer: case ev_integer: case ev_variant: + case ev_function: if (*name && *name != '<') sprintf(newname, "%s%s.%s", name, array, type->params[partnum].paramname); else @@ -9221,6 +9222,10 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, if (!def) { def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved); + if (parttype->type == ev_function) + def->initialized = true; + ((int *)qcc_pr_globals)[def->ofs] = *fieldofs; + *fieldofs += parttype->size; } else { @@ -9228,19 +9233,6 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, QCC_PR_ParsePrintDef(WARN_CONFLICTINGUNIONMEMBER, def); } break; - - case ev_function: - if (*name && *name != '<') - sprintf(newname, "%s%s.%s", name, array, parttype->name); - else - sprintf(newname, "%s%s", parttype->name, array); - ftype = QCC_PR_NewType("FIELD_TYPE", ev_field, false); - ftype->aux_type = parttype; - def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved); - def->initialized = true; - ((int *)qcc_pr_globals)[def->ofs] = *fieldofs; - *fieldofs += parttype->size; - break; case ev_void: break; } diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index d166d360d..9dff0d18a 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -168,13 +168,16 @@ struct { // {"", WARN_KEYWORDDISABLED}, // {"", WARN_ENUMFLAGS_NOTINTEGER}, // {"", WARN_ENUMFLAGS_NOTBINARY}, -// {"", WARN_CASEINSENSATIVEFRAMEMACRO}, {" Q111", WARN_DUPLICATELABEL}, {" Q201", WARN_ASSIGNMENTINCONDITIONAL}, {" F300", WARN_DEADCODE}, {" F301", WARN_NOTUTF8}, {" F302", WARN_UNINITIALIZED}, {" F303", WARN_EVILPREPROCESSOR}, + {" F304", WARN_UNARYNOTSCOPE}, + {" F305", WARN_CASEINSENSATIVEFRAMEMACRO}, + {" F306", WARN_SAMENAMEASGLOBAL}, + {" F307", WARN_STRICTTYPEMISMATCH}, //frikqcc errors //Q608: PrecacheSound: numsounds