graphitemaster / gmqcc

An Improved Quake C Compiler
Other
163 stars 29 forks source link

Inconsistent math with multiple assignments to the same variable #196

Open terencehill opened 3 years ago

terencehill commented 3 years ago
float myfloat, res;
res = (myfloat = 4) - (myfloat = 3); // res == 1
res = (myfloat = 4, myfloat) - (myfloat = 3, myfloat); // res == 0

Both operations should produce the same result, if I'm not mistaken, whereas the former returns 1, the latter 0.

The same operations in C produce the same result (0) at least in this online compiler: https://onlinegdb.com/rJTVFGcJO

terencehill commented 3 years ago

I spotted this inconsistent behavior using Xonotic's vec2 macro:

noref vector _vec2;
#define vec2(...) EVAL(OVERLOAD(vec2, __VA_ARGS__))
#define vec2_1(v) (_vec2 = (v), _vec2.z = 0, _vec2)
#define vec2_2(x, y) (_vec2_x = (x), _vec2_y = (y), _vec2)

vec2(v1) - vec2(v2) always returns '0 0 0' regardless of the values of v1 and v2, so, assuming '0 0 0' is the correct result, operations with more than one call to vec2 in a single assignment should be avoided in the qc code.

Blub commented 3 years ago

After some discussions we think that this should emit a warning but is otherwise not really a "bug". Given C's definition of sequencing, the result types of assignments and, in fact, some compilers warning about code with multiple assignments to the same variable in one expression, I think that's the best way to go. IMO our results make just as much sense as C's. In fact, if anything, I'd consider the 2nd one to be off, but that one does match C...