aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2021-10-15 10:58:56 +0100
committerJonathan Wakely <jwakely@redhat.com>2021-10-15 18:26:53 +0100
commite27771e5dcd8cf2cb757db6177a3485acd28b88f (patch)
tree3e20a8f7438b874abb66dd4d0c83d8c68a77300b /gcc
parent1ba7adabf29eb671e418692fad076ea6edd08e3d (diff)
downloadgcc-e27771e5dcd8cf2cb757db6177a3485acd28b88f.zip
gcc-e27771e5dcd8cf2cb757db6177a3485acd28b88f.tar.gz
gcc-e27771e5dcd8cf2cb757db6177a3485acd28b88f.tar.bz2
libstdc++: Remove try/catch overhead in std::variant::emplace
The __variant_construct_by_index helper function sets the new index before constructing the new object. This means that if the construction throws then the exception needs to be caught, so the index can be reset to variant_npos, and then the exception rethrown. This means callers are responsible for restoring the variant's invariants and they need the overhead of a catch handler and a rethrow. If we don't set the index until after construction completes then the invariant is never broken, and callers can ignore the exception and let it propagate. The callers all call _M_reset() first, which sets index to variant_npos as required while the variant is valueless. We need to be slightly careful here, because changing the order of operations in __variant_construct_by_index and removing the try-block from variant::emplace<I> changes an implicit ABI contract between those two functions. If the linker were to create an executable containing an instantiation of the old __variant_construct_by_index and an instantiation of the new variant::emplace<I> code then we would have a combination that breaks the invariant and doesn't have the exception handling to restore it. To avoid this problem, we can rename the __variant_construct_by_index function so that the new emplace<I> code calls a new symbol, and is unaffected by the behaviour of the old symbol. libstdc++-v3/ChangeLog: * include/std/variant (__detail::__variant::__get_storage): Remove unused function. (__variant_construct_by_index): Set index after construction is complete. Rename to ... (__detail::__variant::__construct_by_index): ... this. (variant): Use new name for __variant_construct_by_index friend declaration. Remove __get_storage friend declaration. (variant::emplace): Use new name and remove try-blocks.
Diffstat (limited to 'gcc')
0 files changed, 0 insertions, 0 deletions