From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id CBB1A39A084D; Wed, 21 Jul 2021 02:51:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CBB1A39A084D From: "brooks at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug libstdc++/101542] New: __gnu_cxx::sequence_buffer const copy constructor is badly broken Date: Wed, 21 Jul 2021 02:51:20 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: libstdc++ X-Bugzilla-Version: unknown X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: brooks at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Jul 2021 02:51:20 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D101542 Bug ID: 101542 Summary: __gnu_cxx::sequence_buffer const copy constructor is badly broken Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: brooks at gcc dot gnu.org Target Milestone: --- This problem showed up when we were running the GCC 4.9.4 testsuite with the latest Clang trunk as the compiler, and found that the ext/rope/4.cc test started failing -- producing "wibblewibble" when it should produce "wibble". However, the problem is broader than that, and affects much more current GCC versions as well -- as can be seen at https://godbolt.org/z/74W78rdWP.=20 Compiling the following program with Clang trunk produces "hellohello" as output: ---- #include #include template T make_copy(const T &x) { return x; } int main() { std::string s; __gnu_cxx::sequence_buffer a(s); { __gnu_cxx::sequence_buffer b =3D a; b.push_back('h'); b.push_back('e'); b.push_back('l'); b.push_back('l'); b.push_back('o'); // Making a copy causes sequence_buffer to break. make_copy(b); } std::cout << s; } ---- This started failing with a recent Clang change (https://github.com/llvm/llvm-project/commit/7d2d5a3a6d7aaa40468c30250bf6b0= 938ef02c08), described as "Apply P1825 as Defect Report from C++11 up to C++20". See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1825r0.html for the defect report details. I would guess that GCC will be applying a similar change. My colleagues Jorge Gorbe and Richard Smith did a lot of digging on this, a= nd Richard explains the problem as follows: ---- The problem with sequence_buffer is that the sequence_buffer(const sequence_buffer&) copy constructor copies the pending characters in the buf= fer to the new copy, and when both are destroyed, they get flushed to the underlying sequence twice. But sequence_buffer is more broken than that: it also has another construct= or, sequence_buffer(sequence_buffer&) that has different semantics: it flushes = the source first. So if you only ever use non-const sequence_buffer objects, ne= ver modify a copied-from object, and never do anything that would call the sequence_buffer(const sequence_buffer&) constructor, it will appear to work. And that's what this test was relying on. Part of the consequence of the Clang change is that in code like this: sequence_buffer f(sequence_buffer x) { return x; } ... the return statement unconditionally behaves like return (sequence_buffer&&)x;. And that means that we now choose the sequence_buffer(const sequence_buffer&) constructor, not the sequence_buffer(sequence_buffer&) constructor, because a non-const lvalue reference can't bind to an rvalue. Ultimately, I think that happens at line 342 of stl_algobase.h ("return __result"), here: https://gcc.gnu.org/git?p=3Dgcc.git;a=3Dblame;f=3Dlibstdc%2B%2B-v3/include/= bits/stl_algobase.h;hb=3D9b61c47826156fe17fd5f4306470ade01e2fc4dc#l238. So: this libstdc++ code is broken, and the test really should never have passed. ---- In our case, we're simply xfailing the test since we don't have any code th= at uses __gnu_cxx::sequence_buffer or __gnu_cxx::rope, but I'm passing this bug report along in hopes that it's useful to the libstdc++ maintainers. :)=