[Bug libstdc++/103853] std::forward_list::merge should check if __list != this

redi at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Dec 29 10:12:32 GMT 2021


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103853

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2021-12-29
             Status|UNCONFIRMED                 |NEW
     Ever confirmed|0                           |1

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Pavel I. Kryukov from comment #0)
> C++ standard does not require 'do nothing' if std::forward_list::merge
> argument equals to 'this', however it does not say 'undefined behavior' or
> 'infinite loop' too.

It does say undefined behaviour for the overload your patch changes.

[res.on.arguments] says:

> If a function argument is bound to an rvalue reference parameter, the
> implementation may assume that this parameter is a unique reference to this
> argument, except that the argument passed to a move-assignment operator may
> be a reference to *this ([lib.types.movedfrom]).

Passing *this as the first parameter of merge(forward_list&&) or
merge(forward_list&&, Comp) breaks this assumption, resulting in undefined
behaviour.

The check is only needed for the overloads taking forward_list& parameters:

--- a/libstdc++-v3/include/bits/forward_list.h
+++ b/libstdc++-v3/include/bits/forward_list.h
@@ -1267,7 +1267,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER

       void
       merge(forward_list& __list)
-      { merge(std::move(__list)); }
+      {
+       if (std::__addressof(__list) == this)
+         return;
+
+       merge(std::move(__list));
+      }

       /**
        *  @brief  Merge sorted lists according to comparison function.
@@ -1287,7 +1292,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       template<typename _Comp>
        void
        merge(forward_list& __list, _Comp __comp)
-       { merge(std::move(__list), __comp); }
+       {
+         if (std::__addressof(__list) == this)
+           return;
+
+         merge(std::move(__list), __comp);
+       }

       /**
        *  @brief  Sort the elements of the list.


> I've attached my patch to fix and test it, but since I'm not an experienced
> GCC contributor, I don't know how to run the tests. Following instructions
> on CONTRIBUTING page builds whole GCC ending with some problems with my
> machine. I would be grateful if you tell how I can test only libstdc++.

You need to build the whole of GCC to test libstdc++, so if you can't get that
working, you should fix that first.

Testing libstdc++ is documented at
https://gcc.gnu.org/onlinedocs/libstdc++/manual/test.html#test.run


More information about the Gcc-bugs mailing list