Path: utzoo!attcan!uunet!lll-winken!ames!pasteur!ucbvax!decwrl!labrea!polya!kaufman From: kaufman@polya.Stanford.EDU (Marc T. Kaufman) Newsgroups: comp.sys.mac.programmer Subject: Re: serious code generation bug in Lightspeed C Message-ID: <6054@polya.Stanford.EDU> Date: 12 Jan 89 17:00:14 GMT References: <6275@hoptoad.uucp> Reply-To: kaufman@polya.Stanford.EDU (Marc T. Kaufman) Organization: Stanford University Lines: 55 In article <6275@hoptoad.uucp> tim@hoptoad.uucp (Tim Maroney) writes: >There is a serious bug in how Lightspeed C handles the assignment >operation. The lvalue is evaluated before the value is computed. This >means that assigments to relocatable structure members do not work >correctly. I disagree that this is a bug. This is how I want the compiler to work. The flip side of the coin is statements like: *p = ++*p; I guess I would argue that a programmer wanting to write bulletproof code that will survive compiler "improvements" and optimizer changes would go out of his way to avoid writing order-of-evaluation dependent code. How about: HLock(h); (*h)->p = NewPtr(size); HUnlock(h); since NewPtr is specifically named as a procedure that can have a side effect of moving unlocked blocks (yes, I know, you don't want to do that here because you couldn't move h out of the way to make room). >For example, suppose you have a relocatable data structure and a handle >to that structure in "h". Further suppose that one member of the >structure referred to by "h" is of type Ptr, called "p". Then this >straightforward statement gives an incorrect result: ^^^^^^^^^ (you mean "unanticipated") (*h)->p = NewPtr(size); >The address of "(*h)->p", the lvalue, is computed before the right-hand >side is evaluated. The address of "(*h)->p" may change as a result of >the NewPtr trap, therefore it may be wrong on return from the trap and >the result of NewPtr may be assigned into invalid memory. >This is pretty amazing,... No, it isn't. Many languages actually require the LHS to be evaluated before the RHS, so that side effects with things like index values don't occur. (FORTRAN comes to mind). I don't think that C requires this, but it doesn't prohibit it. It is, in fact, the obvious order of evaluation if you walk the expression tree in the order it was generated. It is, in fact, the way Algol is specified, and the way Algol machines (such as the Burroughs B5500 et. al.) work internally. > even for a compiler like Think's that >deliberately produces low-budget, non-optimized code. There is a >work-around, assigning the result of NewPtr into an intermediate >variable and then assigning it to the lvalue, but it is unwieldy, and >it is difficult to spot all places where this compiler bug could bite. Again, this is NOT a compiler bug. It is a programmer bug. You shouldn't depend on order-of-evaluation defaults. Marc Kaufman (kaufman@polya.stanford.edu)