Bug 80676

Summary: [DR 2995] basic_stringbuf does not use initial capacity of SSO string
Product: gcc Reporter: Jonathan Wakely <redi>
Component: libstdc++Assignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: enhancement CC: paolo.carlini, webrown.cpp
Priority: P3    
Version: 8.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2017-05-08 00:00:00

Description Jonathan Wakely 2017-05-08 18:02:31 UTC
The following prints "overflow":

#include <sstream>
#include <iostream>

struct SB : std::stringbuf
{
  int_type overflow(int_type c) override
  {
    std::cout << "overflow\n";
    return std::stringbuf::overflow(c);
  }
};

int main()
{
  SB sb;
  std::ostringstream s;
  s.std::ios::rdbuf(&sb);
  s.put('a');
}

The call to the virtual function should not be necessary when using the new ABI, because the SSO string has an initial non-zero capacity. The stringbuf could use it.
Comment 1 Jonathan Wakely 2017-05-08 19:33:08 UTC
The fix is trivial:

--- a/libstdc++-v3/include/std/sstream
+++ b/libstdc++-v3/include/std/sstream
@@ -99,7 +99,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       explicit
       basic_stringbuf(ios_base::openmode __mode = ios_base::in | ios_base::out)
       : __streambuf_type(), _M_mode(__mode), _M_string()
-      { }
+      {
+#if _GLIBCXX_USE_CXX11_ABI
+       _M_stringbuf_init(__mode);
+#endif
+      }
 
       /**
        *  @brief  Starts with an existing string buffer.

There was no point calling _M_stringbuf_init for the COW string, because immediately after construction there was no buffer to use. With an SSO string that isn't true.
Comment 2 Jonathan Wakely 2017-07-10 09:26:47 UTC
This change would break a number of tests which were added specifically to ensure that the sequence pointers are all null after construction:
https://gcc.gnu.org/ml/libstdc++/2004-09/msg00247.html

I've reported a new issue to relax the requirements so we can make this change:
https://wg21.link/lwg2995

This change would also fix Bug 81338 but for now I'll have to fix that in stringbuf::overflow, rather than optimising it to not call overflow.
Comment 3 Jakub Jelinek 2018-05-02 10:11:27 UTC
GCC 8.1 has been released.
Comment 4 Jonathan Wakely 2018-12-12 20:00:38 UTC
The C++2a draft now says:
"It is implementation-defined whether the sequence pointers (eback(), gptr(), egptr(), pbase(), pptr(), epptr()) are initialized to null pointers."