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

Reply via email to