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