Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!snorkelwacker!apple!goofy.apple.com!scott From: scott@goofy.apple.com (scott douglass) Newsgroups: comp.lang.c++ Subject: subtle inlining/sequence points bug in CFront 2.0 Keywords: inline, CFront, bug Message-ID: <8066@goofy.Apple.COM> Date: 4 May 90 08:48:12 GMT Sender: usenet@Apple.COM Organization: Apple Computer Inc., Cupertino, CA Lines: 51 I've found, actually I have been burned by, a subtle bug involving inlining and sequence points in CFront 2.0. In some cases CFront accidentally eliminates the sequence point before the call of an inline function. Example: class A { public: A* next; int i; A* get_next(); int f(); }; A* A::get_next() { return next; } void g(A* a) { int b = ( a->get_next()->i == a->f() ); } Assume that A::f() may change A::next which CFront must since A::f() if not a const member. Since order of evaluation is not defined for expressions either a->get_next() or a->f() will happen first, but the "->i" will definetly refer to one of two possible As. Now the problem. If I make A::get_next() inline CFront generates code something like the following: b = ( a->next->i == f(a) ); The semantics of this expression are not defined. Your C compiler may, and mine did, evaluate a->next into a temporary, evaluate a->f() which may change a->next, and finally evaluate temporary->i which may no longer be valid. One unsavory way that CFront could avoid this would be to introduce it's own temporary like this: int temp; b = ( (temp = a->next->i, temp) == f(a) ); Always introducing such temporaries could be a serious performance hit. A similar temporary is already introduced already when inlining a function such as: inline void A::set_next(A* a) { next = a; } Any comments, especially from people in a position to change CFront?