FIx regression with member tag of an enum not being checked on assigment

This commit is contained in:
Arkshine 2014-12-09 22:26:59 +01:00
parent 2bba5ce69a
commit 45bf43d76e
2 changed files with 31 additions and 4 deletions

View File

@ -240,6 +240,7 @@ typedef struct s_value {
cell constval; /* value of the constant expression (if ident==iCONSTEXPR)
* also used for the size of a literal array */
int tag; /* tagname id (of the expression) */
char forceuntag; /* whether expression is untagged using _: */
char ident; /* iCONSTEXPR, iVARIABLE, iARRAY, iARRAYCELL,
* iEXPRESSION or iREFERENCE */
char boolresult; /* boolean result for relational operators */

View File

@ -973,10 +973,33 @@ static int hier14(value *lval1)
store(&lval3); /* now, store the expression result */
} /* if */
if (!oper) { /* tagname mismatch (if "oper", warning already given in plunge2()) */
if (lval3.sym && !matchtag(lval3.sym->tag, lval2.tag, TRUE))
error(213);
else if (!lval3.sym && !matchtag(lval3.tag, lval2.tag, TRUE))
/* If left value is a symbol and is tagged, we want to check that first.
If we tag array and an enum member is passed as index, we assume enum
is a simple list of constants (as opposite, not a "structure"). E.g.:
enum X {A, B}; new Float:array[X];
array[A] = 1.0;
^ tag of array is checked instead of tag of A.
*/
if (lval3.sym && lval3.sym->tag != 0) {
if (!matchtag(lval3.sym->tag, lval2.tag, TRUE))
error(213);
}
else if (lval3.tag && !lval2.tag && lval2.forceuntag) {
/* Because of the above fix included in AMXX 1.60, a regression has been introduced
as well, where any tagged members of an enum is ignored when a tag check is required.
E.g.: enum X {Float:A, SomeTag:B }; new array[X];
array[A] = 1.0;
With the original fix, tag of array is checked instead of tag of A. Result: tag mismatch.
To bypass the issue, plugin has to untag the value like _:1.0.
To fix this and to avoid old plugins suddenly getting spammed by warnings, we track
when a value is untagged, and if the related enum member is tagged and the value is forced
to be untagged, we assume this matches.
*/
}
else if (!matchtag(lval3.tag, lval2.tag, TRUE)) {
error(213);
}
}
if (lval3.sym)
markusage(lval3.sym,uWRITTEN);
@ -1122,11 +1145,12 @@ static int hier3(value *lval)
static int hier2(value *lval)
{
int lvalue,tok;
int tag,paranthese;
int tag, paranthese;
cell val;
char *st;
symbol *sym=NULL;
int saveresult;
char forceuntag=FALSE;
sym = NULL;
tok=lex(&val,&st);
@ -1201,8 +1225,10 @@ static int hier2(value *lval)
return FALSE;
case tLABEL: /* tagname override */
tag=pc_addtag(st);
forceuntag=(*st == '_'); /* forced to be untagged with _: */
lvalue=hier2(lval);
lval->tag=tag;
lval->forceuntag=forceuntag;
return lvalue;
case tDEFINED:
paranthese=0;