istream::seekg broken in Xcode 6.3's libc++?

We recently switched from using libstc++ to libc++ in our code base, so that we could move up to using C++11, and found to our horror that istream::seekg seems to be broken for custom streams. We use a lot of different custom stream objects, so this is rather worrying.


It looks like this is not a problem with libc++'s implementation of the standard, per se, but some sort of a ABI difference between the compiled library that ships with Xcode 6.3 and clang's output that links with it.


Here's a sample piece of code:

#include <iostream>
#include <cassert>


class custombuf : public std::streambuf
{
public:
    virtual pos_type seekoff(
        off_type offset,
        std::ios_base::seekdir dir,
        std::ios_base::openmode mode = std::ios_base::out |
                        std::ios_base::in)
    {
        return pos_type(off_type(-1));
    }
};


class customstream : public std::istream
{
public:
    customstream() : std::istream(&m_buf) {}


private:
    custombuf   m_buf;
};


int main()
{
    customstream c;
    c.clear();
    c.seekg(-5, std::ios_base::beg);

    // seekoff() in our custom buffer always returns -1, which should cause seekg() to
    // mark the call as failed.
    assert(c.fail());
    return 0;
}


This is then compiled with:

> clang++ -o custombuf custombuf.cpp


Under normal circumstances, the assert on line 38 should not fire, since seekoff() is indicating that we cannot seek, and so seekg() should have set the fail bit. However the comparison between the return value of seekoff() and pos_type(-1) in seekg fails and so that doesn't happen.


I've logged a bug with Apple a week back, but haven't seen a response yet. I was wondering if someone else had run into this and had any suggestions (aside from re-compiling libc++ and shipping our own version, which would be rather sub-optimal).

I'm not sure I understand the question. The purpose of the code is exclusively to trigger the fail bit to be set by seekg(), which is not what happens, indicating that libc++ is broken. This exact same code works as expected with MSVC 2012 & 2015; all gcc versions on Linux, from 4.2 up to 4.9; and, on OSX using the stdlibc++ library from gcc 4.2.


Now, whether I return -1, pos_type(-1), or pos_type(off_type(-1)), in seekoff() doesn't matter at all. The last one is the standard way of doing it, though. Makes the cast chain explicit.

Have a look at sections 27.6.3.4.2 and 27.7.2.3/43 of the C++ standard, and then feel free to come back to educate me at your leisure.


If anyone from Apple is reading, this issue is logged as #21505508.

Thanks for the bug report. This will be fixed in an upcoming El Capitan release.

istream::seekg broken in Xcode 6.3's libc&#43;&#43;?
 
 
Q