Skip to content

<ostream>: Exception from streambuf should be caught and not rethrown #4322

Description

Originally reported as DevCom-10555755 / VSO-1939195 / AB#1939195 . I've cleaned up the repro and especially the Standardese citations, so I believe this is a bug.

D:\GitHub\STL\out\x64>type meow.cpp
#include <cassert>
#include <iostream>
#include <sstream>
#include <stdexcept>
using namespace std;

class MyStreamBuf : public streambuf {
protected:
    // N4971 [streambuf.virt.get]/1-2:
    // "streamsize showmanyc();
    // Returns: An estimate of the number of characters available in the sequence, or -1.
    // If it returns a positive value, then successive calls to underflow() will not return
    // traits::eof() until at least that number of characters have been extracted from the stream.
    // If showmanyc() returns -1, then calls to underflow() or uflow() will fail. [Note 277]
    // Default behavior: Returns zero."

    // Note 277:
    // "underflow or uflow can fail by throwing an exception prematurely. The intention
    // is not only that the calls will not return eof() but that they will return "immediately"."

    int_type underflow() override {
        throw runtime_error("WOOF");
    }
};

int main() {
    MyStreamBuf rdbuf;
    ostringstream oss;
    assert(oss.exceptions() == ios_base::goodbit);

    try {
        // N4971 [ostream.inserters]/8-9:
        // "basic_ostream& operator<<(basic_streambuf<charT, traits>* sb);
        // Gets characters from sb and inserts them in *this. Characters are
        // read from sb and inserted until any of the following occurs:
        // [...]
        // - an exception occurs while getting a character from sb.
        // If the function inserts no characters, it calls setstate(failbit) (which
        // may throw ios_base::failure ([iostate.flags])). If an exception was thrown
        // while extracting a character, the function sets failbit in the error state,
        // and if failbit is set in exceptions() the caught exception is rethrown."
        oss << &rdbuf;
        cout << "No exception observed in main().\n";
    } catch (const runtime_error&) {
        cout << "Caught runtime_error in main().\n";
    }

    assert(oss.rdstate() == ios_base::failbit);
}
D:\GitHub\STL\out\x64>cl /EHsc /nologo /W4 /MTd /Od meow.cpp && meow
meow.cpp
Caught runtime_error in main().

libstdc++ and libc++ print "No exception observed in main()." as shown by https://godbolt.org/z/Yq3noKn8s .

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixedSomething works now, yay!

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions