Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watmath!clyde!rutgers!mit-eddie!uw-beaver!apollo!wanginst!mckeeman From: mckeeman@wanginst.UUCP Newsgroups: comp.lang.c Subject: Re: C and overflow anomolies Message-ID: <1005@wanginst.EDU> Date: Mon, 13-Apr-87 14:01:00 EST Article-I.D.: wanginst.1005 Posted: Mon Apr 13 14:01:00 1987 Date-Received: Sat, 18-Apr-87 08:28:55 EST References: <15958@sun.uucp> <5716@brl-smoke.ARPA> <14680@cca.CCA.COM> <568@csun.UUCP> Organization: Wang Institute Lines: 82 Summary: x3j11, optimization, and integer overflow Let me focus on one particular point of the draft standard that may be read differently by C programmers and C compiler writers. First the raw data: (from the July 9 draft from x3j11) 2.1.2.3 Program execution ... Evaluation of an expression (specifically, one that involves assignment, incrementing, decrementing, or calling a function that does any of those operations) may produce _side_effects_, which are changes in the state of the execution environment incidental to the evaluation. At certain specified points in the execution sequence, called _sequence_points_, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place. 3.6 Statements ... Except as indicated, statements are executed in sequence. ... The end of a _full_expression_ is a sequence point. Analysis: Point 1. the final appearance of "side" in the paragraph above should be stricken. In fact it is necesary that _no_ effects of subsequent evaluations shall have taken place. Example: x=y; z=x; The side effect of storing into x must precede the (non-side-effect) fetch of x in the second statement. I suppose that is what the authors intended. Point 2. compilers may, in fact, discard explicit assignments x=y; z=x; In the case that the above is the only use of x, and absent directives such as volatile and implicit casts, some compiler writers feel free to not allocate storage for x and translate the above as: z=y; The reasoning is that the _observable_ effect of the more efficient version is the same as the one the programmer wrote. This is harmless enough unless the programmer is poking around with a debugger or looking at a postmortem. If the x3j11 document is supposed to forbid this optimization, then it had better say something like "all assignments and {inc|dec}rements must result in updating the indicated memory location." Point 3. point 2 can get you (or me) into trouble Many compiler writers would treat the following assignments likewise: x=y+1; z=x-1; turning into z=y; which is fine except where y==MAXINT. This is an example of optimizers that work except for expressions that overflow. I think x3j11 is OK on this point (the compiler writer is surely violating it) but x3j11 could explicitly forbid optimizations that fail to preserve semantics for expressions that {over|under}flow. Deep in the heart and professional aspirations of some compiler writers is an urge to ignore non-arithmetic properties of computer arithmetic, and a suspicion that customers would rather have really fast code than code that preserves the semantics of overflow for those very rare cases where it matters. End of Points. The innocent examples above do not expose the subtlety of the problem for complex expressions, but resolving the meaning of x3j11 for the above should constrain/free the compiler writer as needed. QUESTION: Is it worth tinkering with the x3j11 verbiage? QUESTION: Should all explicit assignments be forced to memory? QUESTION: Should compiled code overflow exactly the same way under all implementations? -- W. M. McKeeman mckeeman@WangInst Wang Institute decvax!wanginst!mckeeman Tyngsboro MA 01879