This is an archive of the discontinued LLVM Phabricator instance.

[libcxx] [test] Changes to accommodate LWG 2904 "Make variant move-assignment more exception safe"
AbandonedPublic

Authored by CaseyCarter on Apr 25 2017, 5:40 PM.

Details

Summary
NOTE: TEST CHANGES ONLY.

These tests will not pass with the current implementation of variant, but should give the implementor of LWG2904 a head start.

Details:

test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp:

  • Make CopyAssign's move operations noexcept so uses in variants continue to prefer copy-and-move over direct construction.
  • Fix makeEmpty: Copy assignment syntax no longer invokes MakeEmptyT's throwing move constructor, move assignment syntax still does.
  • test_copy_assignment_sfinae: variant<int, CopyOnly> is now copy assignable.
  • test_copy_assignment_different_index:
    • CopyThrows and MoveThrows have potentially-throwing move construction, so they are now copy constructed directly into variants instead of via indirect copy-and-move.
    • implement new CopyCannotThrow and verify that direct copy construction of such in variants is preferred over indirect copy-and-move when neither method throws.

test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp:

  • test_move_assignment_sfinae: variant<int, MoveOnly> is now move assignable.

test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp:

  • test_T_assignment_performs_construction:
    • assigning ThrowsCtorT into a variant now constructs a temporary and moves into the variant; the variant keeps its old value if the temporary construction throws.
    • test that direct construction is preferred to temporary-and-move when neither can throw.
    • test that direct construction is preferred to temporary-and-move when both can throw.

test/support/variant_test_helpers.hpp:
test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp:
test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp:

  • Fix makeEmpty: Copy assignment syntax no longer invokes MakeEmptyT's throwing move constructor, move assignment syntax still does.

Diff Detail

Event Timeline

CaseyCarter created this revision.Apr 25 2017, 5:40 PM

Added some inline notes for reviewers.

test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp
195

Reviewer note: After LWG 2904, the assignment on 191 uses a new "emplace from temporary" path. The temporary creation now throws *before* v becomes valueless.

test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp
168

Reviewer note: This comment is no longer true after LWG 2904 copy assignment no longer requires move constructible alternatives.

test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp
121

Reviewer note: this comment is technically true even after LWG 2904, but no longer significant. variant<int, CopyOnly> *does* have an implicitly deleted move assignment operator, but is_move_assignable_v<variant<int, CopyOnly>> is nonetheless true after LWG 2904 since variant<int, CopyOnly> now has a viable *copy* assignment operator.

mpark edited edge metadata.May 23 2017, 5:53 PM

Thanks for the tests! I'll try this out with an implementation shortly.

CaseyCarter abandoned this revision.Jun 5 2017, 6:12 PM

Abandoning: these changes have been merged into D32671.