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) cell constval; /* value of the constant expression (if ident==iCONSTEXPR)
* also used for the size of a literal array */ * also used for the size of a literal array */
int tag; /* tagname id (of the expression) */ int tag; /* tagname id (of the expression) */
char forceuntag; /* whether expression is untagged using _: */
char ident; /* iCONSTEXPR, iVARIABLE, iARRAY, iARRAYCELL, char ident; /* iCONSTEXPR, iVARIABLE, iARRAY, iARRAYCELL,
* iEXPRESSION or iREFERENCE */ * iEXPRESSION or iREFERENCE */
char boolresult; /* boolean result for relational operators */ char boolresult; /* boolean result for relational operators */

View File

@ -973,11 +973,34 @@ static int hier14(value *lval1)
store(&lval3); /* now, store the expression result */ store(&lval3); /* now, store the expression result */
} /* if */ } /* if */
if (!oper) { /* tagname mismatch (if "oper", warning already given in plunge2()) */ if (!oper) { /* tagname mismatch (if "oper", warning already given in plunge2()) */
if (lval3.sym && !matchtag(lval3.sym->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); error(213);
else if (!lval3.sym && !matchtag(lval3.tag, lval2.tag, TRUE)) }
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); error(213);
} }
}
if (lval3.sym) if (lval3.sym)
markusage(lval3.sym,uWRITTEN); markusage(lval3.sym,uWRITTEN);
sideeffect=TRUE; sideeffect=TRUE;
@ -1127,6 +1150,7 @@ static int hier2(value *lval)
char *st; char *st;
symbol *sym=NULL; symbol *sym=NULL;
int saveresult; int saveresult;
char forceuntag=FALSE;
sym = NULL; sym = NULL;
tok=lex(&val,&st); tok=lex(&val,&st);
@ -1201,8 +1225,10 @@ static int hier2(value *lval)
return FALSE; return FALSE;
case tLABEL: /* tagname override */ case tLABEL: /* tagname override */
tag=pc_addtag(st); tag=pc_addtag(st);
forceuntag=(*st == '_'); /* forced to be untagged with _: */
lvalue=hier2(lval); lvalue=hier2(lval);
lval->tag=tag; lval->tag=tag;
lval->forceuntag=forceuntag;
return lvalue; return lvalue;
case tDEFINED: case tDEFINED:
paranthese=0; paranthese=0;