CVS g++ produces incorrect code when compiling the following file with -Os. There does not appear to be a problem with gcc 4.0.
--- Begin op_test.cpp #include <iostream> using namespace std; class Pair { protected: int a; int b; public: Pair(){} Pair(int x, int y) : a(x), b(y) {} int Product() const { return a*b; } }; class PairSet { public: class Iter; friend class Iter; protected: class List { public: Pair mPair; List* mNext; List(){} }; List* mPairs; public: PairSet() : mPairs(NULL) {} class Iter { public: Iter(List* aPairList) : mCurrent(aPairList) {} Iter& operator++() { List* next = mCurrent->mNext; mCurrent = next; return *this; } const Pair* operator->() const { return &mCurrent->mPair; } int operator!=(const Iter& aIter) const { return mCurrent != aIter.mCurrent; } protected: List* mCurrent; }; Iter First() const { return Iter(mPairs); } Iter Last() const { return Iter(NULL); } void Add(const Pair& aElement); }; void PairSet::Add(const Pair& aElement) { List *list = new List(); list->mNext = mPairs; list->mPair = aElement; mPairs = list; } int main() { int result = 0; PairSet ps; ps.Add(Pair(2,3)); ps.Add(Pair(4,5)); PairSet::Iter last = ps.Last(); for(PairSet::Iter iter = ps.First(); iter != last; ++iter) result += iter->Product(); cout << result << endl; return 0; } --- End op_test.cpp class Pairset::Iter allows a loop to step through a list of pointers to Pair objects using operator++, and provides access to the Pair objects through operator->. The program should output 26 (the sum of both products, 2*3 + 4*5). With -Os, inspection of the assembly shows that in main() the compiler is "caching" the value of iter-> without realising that calls to ++iter may change it. As a result, Pair::Product() is called on the (4,5) pair twice, giving output of 40. For information, the bug appears in Mozilla, function Instantiation::Hash in file ./content/xul/templates/src/nsRuleNetwork.cpp. -- Summary: Incorrect code with -Os Product: gcc Version: 4.1.0 Status: UNCONFIRMED Severity: normal Priority: P2 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: m dot calderbank at iname dot com CC: gcc-bugs at gcc dot gnu dot org GCC build triplet: i686-pc-linux-gnu GCC host triplet: i686-pc-linux-gnu GCC target triplet: i686-pc-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20667