This is an archive of the discontinued LLVM Phabricator instance.

Fix std::inplace_merge to be stable for all inputs
Needs ReviewPublic

Authored by jdoerrie on May 3 2017, 1:21 AM.

Details

Summary

This change fixes std::inplace_merge to be stable for all inputs and adds corresponding tests.

Fixes Bug 31166: https://bugs.llvm.org//show_bug.cgi?id=31166

Diff Detail

Event Timeline

jdoerrie created this revision.May 3 2017, 1:21 AM
jdoerrie added inline comments.May 3 2017, 1:33 AM
include/algorithm
4471

As marshall pointed out in https://bugs.llvm.org//show_bug.cgi?id=31166 this is where the problem lies. While reversing the input ranges is a very nifty trick to be able to use the moved out space at the end of [first, last), simply negating the comparison functor is not enough to preserve stability.

Assuming a default __comp of std::less, in line 4431 a negated __comp will evaluate to true for equivalent elements, resulting in a move from *__first2 and thus breaking stability. The fix for this to to still have __comp evaluate to false for equivalent elements, what the change in 748 accomplishes.

Given that now __negate technically does not negate anymore, maybe it should be renamed to a more suiting __reverse or __swap or similar. Doing a quick grep over the code base line 4471 seems to be the only place where this is used, so a rename should not have further consequences. Furthermore, the unary bool operator() could be deleted.

Ping, please take a look at this.

mclow.lists edited edge metadata.Aug 27 2017, 9:13 PM

I applied the test change, but not the algorithm change, and the tests passed.

Note: I suspect that the proposed change to <algorithm> fixes the problem, but the new tests don't check that.

I committed as r311952 which fixes this - based on Jan's suggestion, but not quite the same as this patch.

Thanks for applying a fix based on my patch! I could have sworn the added tests failed locally before applying the algorithm patch, though... oh well.