Merge pull request #164 from Arkshine/fix/regression-member-tag-of-enum

FIx regression with member tag of enum not being checked on assigment
This commit is contained in:
Vincent Herbet 2014-12-13 11:23:10 +01:00
commit 1df58d6231
2 changed files with 26 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,10 +973,30 @@ 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))
error(213); /* If the left value is a tagged symbol, assume that it is not an "enum struct." For
else if (!lval3.sym && !matchtag(lval3.tag, lval2.tag, TRUE)) example, for "enum X { A, B }; new Float:array[X]" we assume that `A` and `B`
are not tagged and the array is an array of floats.
*/
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); error(213);
}
} }
if (lval3.sym) if (lval3.sym)
markusage(lval3.sym,uWRITTEN); markusage(lval3.sym,uWRITTEN);
@ -1122,7 +1142,7 @@ static int hier3(value *lval)
static int hier2(value *lval) static int hier2(value *lval)
{ {
int lvalue,tok; int lvalue,tok;
int tag,paranthese; int tag, paranthese;
cell val; cell val;
char *st; char *st;
symbol *sym=NULL; symbol *sym=NULL;
@ -1203,6 +1223,7 @@ static int hier2(value *lval)
tag=pc_addtag(st); tag=pc_addtag(st);
lvalue=hier2(lval); lvalue=hier2(lval);
lval->tag=tag; lval->tag=tag;
lval->forceuntag=!tag; /* forced to be untagged with _: */
return lvalue; return lvalue;
case tDEFINED: case tDEFINED:
paranthese=0; paranthese=0;