Chained assignments, automatic type conversion, confusion between logical and bitwise operations...
I hope the community will tolerate my throwing this in as a belated illustration of just /how/ problematic that sort of thing can be.
if ((options == (__WCLONE|__WALL)) && (current->uid = 0))
retval = -EINVAL;
That was a backdoor that person-unknown attempted to get into the Linux kernel back in 2003, as discussed at
https://lwn.net/Articles/57135/HINT: consider carefully the placement of == and = in that.The C-derivative community's response to that has been to mandate a style where comparisons have their less-mutable expression on the left, which reduces (but does not eliminate) the risk of a rogue assignment.
Frankly, this should not be necessary in a computer language: it is an abomination.
To spell it out: the result of (options == (__WCLONE|__WALL)) is a boolean, the result of (current->uid = 0) is an integer. The && (logical-and) operator should only be compatible with booleans, not integers or a mixture of the two.
ALL automatic type conversions are a problem, which is why Wirth became far more strict post-Pascal. In addition, many cases need to distinguish between a bitwise conversion (with assumed zero padding/removal) and functional conversion (e.g. between an integer and float with significant difference in representation): Modula-2 had distinct type-transfer and VAL() operations for this.
Two recent threads provide examples of these problems:
https://forum.lazarus.freepascal.org/index.php/topic,67448.msg518992.html#msg518992 (where a boolean is extended to register size under certain conditions) and
https://forum.lazarus.freepascal.org/index.php/topic,67215.msg516777.html#msg516777 where part of OP's confusion was apparently caused by a shift operator applied to a constant without an explicit associated size.
MarkMLl