diff --git a/compiler/libpc300/sc.h b/compiler/libpc300/sc.h index 1c3cfe0c..359d6fc5 100755 --- a/compiler/libpc300/sc.h +++ b/compiler/libpc300/sc.h @@ -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 */ diff --git a/compiler/libpc300/sc3.c b/compiler/libpc300/sc3.c index a268a1b1..13c45c42 100755 --- a/compiler/libpc300/sc3.c +++ b/compiler/libpc300/sc3.c @@ -973,10 +973,30 @@ 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 the left value is a tagged symbol, assume that it is not an "enum struct." For + 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); + } } if (lval3.sym) markusage(lval3.sym,uWRITTEN); @@ -1122,7 +1142,7 @@ 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; @@ -1203,6 +1223,7 @@ static int hier2(value *lval) tag=pc_addtag(st); lvalue=hier2(lval); lval->tag=tag; + lval->forceuntag=!tag; /* forced to be untagged with _: */ return lvalue; case tDEFINED: paranthese=0;