diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index 8d8b03c..c710dde 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -61,6 +61,8 @@ static int dbltest(void (*oper)(),value *lval1,value *lval2); static int commutative(void (*oper)()); static int constant(value *lval); +static const char str_w247unary[]="a \"bool:\" value"; +static const char str_w247binary[]="\"bool:\" values"; static char lastsymbol[sNAMEMAX+1]; /* name of last function/variable */ static int bitwise_opercount; /* count of bitwise operators in an expression */ static int decl_heap=0; @@ -78,15 +80,15 @@ static void (*op1[17])(void) = { os_le,os_ge,os_lt,os_gt, /* hier9, index 11 */ ob_eq,ob_ne, /* hier10, index 15 */ }; -/* These two functions are defined because the functions inc() and dec() in - * SC4.C have a different prototype than the other code generation functions. +/* These two macros are defined because the functions inc() and dec() in SC4.C + * have a different prototype than the other code generation functions. * The arrays for user-defined functions use the function pointers for * identifying what kind of operation is requested; these functions must all * have the same prototype. As inc() and dec() are special cases already, it - * is simplest to add two "do-nothing" functions. + * is simplest to cast them into "void (*)(void)". */ -static void user_inc(void) {} -static void user_dec(void) {} +#define user_inc ((void (*)(void))inc) +#define user_dec ((void (*)(void))dec) /* * Searches for a binary operator a list of operators. The list is stored in @@ -646,9 +648,29 @@ static void plnge2(void (*oper)(void), lval1->ident=iEXPRESSION; lval1->constval=0; } else { - if ((oper==ob_sal || oper==os_sar || oper==ou_sar) - && (lval2->ident==iCONSTEXPR && (lval2->constval<0 || lval2->constval>=PAWN_CELL_SIZE))) + if (lval1->tag==BOOLTAG && lval2->tag==BOOLTAG + && oper!=ob_or && oper!=ob_xor && oper!=ob_and && oper!=ob_eq && oper!=ob_ne) { + static const void (*opers[])(void) = { + os_mult,os_div,os_mod,ob_add,ob_sub,ob_sal, + os_sar,ou_sar,os_le,os_ge,os_lt,os_gt + }; + static const char* opnames[] = { + "*","/","%","+","-","<<", + ">>",">>>","<=",">=","<",">" + }; + int i; + assert_static(arraysize(opers)==arraysize(opnames)); /* make sure the array sizes match */ + assert_static(arraysize(op1)==17); /* in case a new operator is added into the compiler, + * arrays "opers" and "opnames" might need to be updated */ + for (i=0; iident==iCONSTEXPR && (lval2->constval<0 || lval2->constval>=PAWN_CELL_SIZE))) { error(241); /* negative or too big shift count */ + } /* if */ if (lval1->ident==iCONSTEXPR && lval2->ident==iCONSTEXPR) { /* only constant expression if both constant */ stgdel(lval_stgidx,lval_cidx); /* scratch generated code and calculate */ @@ -1283,8 +1305,11 @@ static int hier2(value *lval) assert(lval->sym!=NULL); if ((lval->sym->usage & uCONST)!=0) return error(22); /* assignment to const argument */ - if (!check_userop(user_inc,lval->tag,0,1,lval,&lval->tag)) + if (!check_userop(user_inc,lval->tag,0,1,lval,&lval->tag)) { + if (lval->tag==BOOLTAG) + error(247,"++",str_w247unary); /* use of operator "++" on a "bool:" value */ inc(lval); /* increase variable first */ + } /* if */ rvalue(lval); /* and read the result into PRI */ pc_sideeffect=TRUE; return FALSE; /* result is no longer lvalue */ @@ -1294,8 +1319,11 @@ static int hier2(value *lval) assert(lval->sym!=NULL); if ((lval->sym->usage & uCONST)!=0) return error(22); /* assignment to const argument */ - if (!check_userop(user_dec,lval->tag,0,1,lval,&lval->tag)) + if (!check_userop(user_dec,lval->tag,0,1,lval,&lval->tag)) { + if (lval->tag==BOOLTAG) + error(247,"--",str_w247unary); /* use of operator "--" on a "bool:" value */ dec(lval); /* decrease variable first */ + } /* if */ rvalue(lval); /* and read the result into PRI */ pc_sideeffect=TRUE; return FALSE; /* result is no longer lvalue */ @@ -1307,7 +1335,7 @@ static int hier2(value *lval) if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL) lval->ident=iEXPRESSION; if (lval->tag==BOOLTAG) - error(makelong(247,3),"!"); /* use of operator "~" on a "bool:" value always results in "true" */ + error(makelong(247,3),"~",str_w247unary,"!"); /* use of operator "~" on a "bool:" value; did you mean to use operator "!"? */ return FALSE; case '!': /* ! (logical negate) */ if (hier2(lval)) @@ -1352,6 +1380,8 @@ static int hier2(value *lval) lval->constval=-lval->constval; if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL) lval->ident=iEXPRESSION; + if (lval->tag==BOOLTAG) + error(makelong(247,3),"-",str_w247unary,"!"); /* use of operator "-" on a "bool:" value; did you mean to use operator "!"? */ } /* if */ return FALSE; case tLABEL: /* tagname override */ @@ -1676,8 +1706,11 @@ static int hier2(value *lval) rvalue(lval); /* read current value into PRI */ if (saveresult) swap1(); /* save PRI on the stack, restore address in PRI */ - if (!check_userop(user_inc,lval->tag,0,1,lval,&lval->tag)) + if (!check_userop(user_inc,lval->tag,0,1,lval,&lval->tag)) { + if (lval->tag==BOOLTAG) + error(247,"++",str_w247unary); /* use of operator "++" on a "bool:" value */ inc(lval); /* increase variable afterwards */ + } /* if */ if (saveresult) popreg(sPRI); /* restore PRI (result of rvalue()) */ pc_sideeffect=TRUE; @@ -1694,8 +1727,11 @@ static int hier2(value *lval) rvalue(lval); /* read current value into PRI */ if (saveresult) swap1(); /* save PRI on the stack, restore address in PRI */ - if (!check_userop(user_dec,lval->tag,0,1,lval,&lval->tag)) + if (!check_userop(user_dec,lval->tag,0,1,lval,&lval->tag)) { + if (lval->tag==BOOLTAG) + error(247,"--",str_w247unary); /* use of operator "--" on a "bool:" value */ dec(lval); /* decrease variable afterwards */ + } /* if */ if (saveresult) popreg(sPRI); /* restore PRI (result of rvalue()) */ pc_sideeffect=TRUE; diff --git a/source/compiler/sc5.c b/source/compiler/sc5.c index 8d4c2c4..ba3e4e3 100644 --- a/source/compiler/sc5.c +++ b/source/compiler/sc5.c @@ -205,14 +205,14 @@ static char *warnmsg[] = { /*244*/ "enum element \"%s\" not handled in switch\n", /*245*/ "enum increment \"%s %d\" has no effect on zero value (symbol \"%s\")\n", /*246*/ "multiplication overflow in enum element declaration (symbol \"%s\")\n", -/*247*/ "use of operator \"~\" on a \"bool:\" value always results in \"true\"\n", +/*247*/ "use of operator \"%s\" on %s\n", /*248*/ "possible misuse of comma operator\n" }; static char *noticemsg[] = { /*001*/ "; did you mean \"%s\"?\n", /*002*/ "; state variable out of scope\n", -/*003*/ "; did you mean operator \"%s\"?\n" +/*003*/ "; did you mean to use operator \"%s\"?\n" }; #define NUM_WARNINGS arraysize(warnmsg) diff --git a/source/compiler/tests/warning_247.meta b/source/compiler/tests/warning_247.meta index 3465835..f4e847a 100644 --- a/source/compiler/tests/warning_247.meta +++ b/source/compiler/tests/warning_247.meta @@ -1,7 +1,24 @@ { 'test_type': 'output_check', 'errors': """ -warning_247.pwn(9) : warning 247: use of operator "~" on a "bool:" value always results in "true"; did you mean operator "!"? -warning_247.pwn(11) : warning 247: use of operator "~" on a "bool:" value always results in "true"; did you mean operator "!"? +warning_247.pwn(35) : warning 247: use of operator "<=" on "bool:" values +warning_247.pwn(36) : warning 247: use of operator ">=" on "bool:" values +warning_247.pwn(37) : warning 247: use of operator "<" on "bool:" values +warning_247.pwn(38) : warning 247: use of operator ">" on "bool:" values +warning_247.pwn(39) : warning 247: use of operator "~" on a "bool:" value; did you mean to use operator "!"? +warning_247.pwn(40) : warning 247: use of operator "-" on a "bool:" value; did you mean to use operator "!"? +warning_247.pwn(41) : warning 247: use of operator "++" on a "bool:" value +warning_247.pwn(42) : warning 247: use of operator "++" on a "bool:" value +warning_247.pwn(43) : warning 247: use of operator "--" on a "bool:" value +warning_247.pwn(44) : warning 247: use of operator "--" on a "bool:" value +warning_247.pwn(45) : warning 247: use of operator "*" on "bool:" values +warning_247.pwn(46) : warning 247: use of operator "/" on "bool:" values +warning_247.pwn(47) : warning 247: use of operator "%" on "bool:" values +warning_247.pwn(48) : warning 247: use of operator "+" on "bool:" values +warning_247.pwn(49) : warning 247: use of operator "-" on "bool:" values +warning_247.pwn(50) : warning 247: use of operator "<<" on "bool:" values +warning_247.pwn(51) : warning 247: use of operator ">>" on "bool:" values +warning_247.pwn(52) : warning 247: use of operator ">>>" on "bool:" values +warning_247.pwn(55) : warning 247: use of operator "~" on a "bool:" value; did you mean to use operator "!"? """ } diff --git a/source/compiler/tests/warning_247.pwn b/source/compiler/tests/warning_247.pwn index 02580e0..4fe65a4 100644 --- a/source/compiler/tests/warning_247.pwn +++ b/source/compiler/tests/warning_247.pwn @@ -1,12 +1,56 @@ main() { - new a = 0, bool:b = false, c; + new bool:a = true, bool:b = false; + new u1 = 1, u2 = 0; + + if (u1) {} + if (!u1) {} + if (~u1) {} + if (-u1) {} + if (++u1) {} + if (u1++) {} + if (--u1) {} + if (u1--) {} + if (u1 || u2) {} + if (u1 ^ u2) {} + if (u1 && u2) {} + if (u1 == u2) {} + if (u1 != u2) {} + if (u1 * u2) {} + if (u1 / u2) {} + if (u1 % u2) {} + if (u1 + u2) {} + if (u1 - u2) {} + if (u1 << u2) {} + if (u1 >> u2) {} + if (u1 >>> u2) {} + if (a) {} - if (b) {} if (!a) {} - if (!b) {} - if (~a) {} // bitwise inversion on an untagged value is OK - if (~b) {} // warning 247: use of operator "~" on a "bool:" value always results in "true"; did you mean operator "!"? - if (~(a & c)) {} // bitwise AND, the result is not forced to be "bool:"-tagged - if (~(a && c)) {} // warning 247: use of operator "~" on a "bool:" value always results in "true"; did you mean operator "!"? + if (a || b) {} + if (a ^ b) {} + if (a && b) {} + if (a == b) {} + if (a != b) {} + if (a <= b) {} // warning 247: use of operator "<=" on "bool:" values + if (a >= b) {} // warning 247: use of operator ">=" on "bool:" values + if (a < b) {} // warning 247: use of operator "<" on "bool:" values + if (a > b) {} // warning 247: use of operator ">" on "bool:" values + if (~a) {} // warning 247: use of operator "~" on a "bool:" value; did you mean to use operator "!"? + if (-a) {} // warning 247: use of operator "-" on a "bool:" value; did you mean to use operator "!"? + if (++a) {} // warning 247: use of operator "++" on a "bool:" value + if (a++) {} // warning 247: use of operator "++" on a "bool:" value + if (--a) {} // warning 247: use of operator "--" on a "bool:" value + if (a--) {} // warning 247: use of operator "--" on a "bool:" value + if (a * b) {} // warning 247: use of operator "*" on "bool:" values + if (a / b) {} // warning 247: use of operator "/" on "bool:" values + if (a % b) {} // warning 247: use of operator "%" on "bool:" values + if (a + b) {} // warning 247: use of operator "+" on "bool:" values + if (a - b) {} // warning 247: use of operator "-" on "bool:" values + if (a << b) {} // warning 247: use of operator "<<" on "bool:" values + if (a >> b) {} // warning 247: use of operator ">>" on "bool:" values + if (a >>> b) {}// warning 247: use of operator ">>>" on "bool:" values + + if (~(u1 & u2)) {} // bitwise AND, the result is not forced to be "bool:"-tagged + if (~(u1 && u2)) {} // warning 247: use of operator "~" on a "bool:" value; did you mean operator "!"? } diff --git a/source/compiler/tests/warning_247_ovl.meta b/source/compiler/tests/warning_247_ovl.meta new file mode 100644 index 0000000..f36c725 --- /dev/null +++ b/source/compiler/tests/warning_247_ovl.meta @@ -0,0 +1,5 @@ +{ + 'test_type': 'output_check', + 'errors': """ +""" +} diff --git a/source/compiler/tests/warning_247_ovl.pwn b/source/compiler/tests/warning_247_ovl.pwn new file mode 100644 index 0000000..8639051 --- /dev/null +++ b/source/compiler/tests/warning_247_ovl.pwn @@ -0,0 +1,36 @@ +// This test makes sure overloaded operators for tag `bool:` don't trigger +// warning 247. The code in 'main()' is copied from file "warning_247.pwn", +// but with the lines that test operators `<<`, `>>`, `>>>` and `~` removed, +// as shift operators can't be overloaded and `~` is reserved for destructors. + +bool:operator -(bool:oper) return oper; +bool:operator ++(bool:oper) return oper; +bool:operator --(bool:oper) return oper; +bool:operator *(bool:oper1, bool:oper2) return oper1,oper2; +bool:operator /(bool:oper1, bool:oper2) return oper1,oper2; +bool:operator %(bool:oper1, bool:oper2) return oper1,oper2; +bool:operator +(bool:oper1, bool:oper2) return oper1,oper2; +bool:operator -(bool:oper1, bool:oper2) return oper1,oper2; +bool:operator <=(bool:oper1, bool:oper2) return oper1,oper2; +bool:operator >=(bool:oper1, bool:oper2) return oper1,oper2; +bool:operator <(bool:oper1, bool:oper2) return oper1,oper2; +bool:operator >(bool:oper1, bool:oper2) return oper1,oper2; + +main() +{ + new bool:a = true, bool:b = false; + if (a <= b) {} + if (a >= b) {} + if (a < b) {} + if (a > b) {} + if (-a) {} + if (++a) {} + if (a++) {} + if (--a) {} + if (a--) {} + if (a * b) {} + if (a / b) {} + if (a % b) {} + if (a + b) {} + if (a - b) {} +}