Fri 17 Jun 2005 12:18:19 AM UTC, original submission:
I recently encountered an error when attempting to build FreePooma using the PathScale Compilers. The test Particles/tests/destroy fails at higher optimization levels. After some investigation, I found what appears to be source bug.
./src/Domain/IntervalIterator.h declares
class IntervalIterator {
inline const Value_t &operator*() const { PAssert(!done()); return val_m; }
};
This works as a standalone iterator, but can result in incorrect behavior when used as an STL reverse_iterator.
This is because /include/c++/3.4.2/bits/stl_iterator.h declares
class reverse_iterator
{
reference
operator*() const
{
_Iterator __tmp = current;
return *--__tmp;
}
};
Here _Iterator is the same type as IntervalIterator, and reference is of type (const IntervalIterator&). When operator() is called for a reverse_iterator it is called on a local copy of IntervalIterator. Thus, when IntervalIterator::operator() returns a constant reference to a member variable, reverse_iterator::operator*() returns pointer to a local variable of the wrong scope. This happens to usually work with g++ because this function is typically inlined.
If I apply the following patch to the source then the test passes with both g++ and pathCC compilers at all optimization levels. As part of this patch, I made operator->() cause an assertion failure. I don't believe it is possible to make this function behave in the expected fashion as long as the value is a member of the iterator.
rock:Domain> diff -u IntervalIterator.h.old IntervalIterator.h
--- IntervalIterator.h.old 2005-06-16 16:18:02.167397996 -0700
+++ IntervalIterator.h 2005-06-16 16:21:51.850573938 -0700
@@ -68,7 +68,7 @@
typedef ptrdiff_t value_type;
typedef ptrdiff_t difference_type;
typedef const ptrdiff_t* pointer;
- typedef const ptrdiff_t& reference;
+ typedef ptrdiff_t reference;
//============================================================
// Constructors
@@ -98,12 +98,12 @@
// Dereference operator. Returns const ref to internal Loc.
- inline const Value_t &operator*() const { PAssert(!done()); return val_m; }
+ inline Value_t operator*() const { PAssert(!done()); return val_m; }
// Member selection operator. Not really useful (ints have no
// members to invoke), but part of the required interface.
- inline const Value_t *operator->() const { PAssert(!done()); return &val_m; }
+ inline const Value_t *operator->() const { PAssert(false); return NULL; }
// Equality tests.
// This only tests that the iterators have the same value.
|