Bug 57049 - std::swap does self move assignment, which is illegal
Summary: std::swap does self move assignment, which is illegal
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.7.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-04-23 15:46 UTC by Tudor Bosman
Modified: 2013-06-11 09:00 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
sample program that illustrates incorrect behavior (251 bytes, application/octet-stream)
2013-04-23 15:46 UTC, Tudor Bosman
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tudor Bosman 2013-04-23 15:46:36 UTC
Created attachment 29922 [details]
sample program that illustrates incorrect behavior

The default implementation of std::swap does self-move-assignment when calling swap(a, a), which is illegal according to 17.6.4.9.
Comment 1 Tudor Bosman 2013-04-23 15:54:18 UTC
Actually, I'll take this back.  I don't believe this is a bug.

17.6.4.9 constraints arguments passed to STL functions.  So if there is a library function that takes a rvalue argument (such as string::operator=(string&& other)), then the library is free to assume that the argument doesn't alias (so &other != this).  So the assertion in basic_fbstring is correct.

The default implementation of swap() does self-move assignment.  That would be illegal if the types were MoveAssignable STL types (because then they'd call T::operator=(T&&) which would be illegal according to 17.6.4.9) BUT ALL STL TYPES HAVE SPECIALIZED IMPLEMENTATIONS OF SWAP which don't do self move assignment.

So the default swap() will do self-move-assignment on user types, but there's no language in the standard that bans self-move-assignment there.
Comment 2 Daniel Krügler 2013-04-25 09:55:47 UTC
Here are two different things to consider:

1) The standard library specification of basic_string's move-assignment operator currently requires that it works for self-assignment:

<quote>
21 Effects: If *this and str are not the same object, modifies *this as shown in Table 71. [...]

22 If *this and str are the same object, the member has no effect.
</quote>

This might or might not change, depending on the outcome of LWG issue

http://cplusplus.github.io/LWG/lwg-active.html#2063

2) The generic swap template from <utility> imposes requirements on the argument types and describes what it does (which can only rely on the requirements). So if you call swap with the same argument value and if for these argument values the move-assignment is undefined behaviour, you get what you are asking for. There is no single evidence that swap would be even allowed to prevent swapping for identical arguments, because the semantics are specified clearly to exchange the two values.
Comment 3 Paolo Carlini 2013-06-11 09:00:38 UTC
Closing then.