libstdc++: Fix capturing of lvalue references in_RangeAdaptor::operator()
authorPatrick Palka <ppalka@redhat.com>
Wed, 19 Feb 2020 19:10:32 +0000 (14:10 -0500)
committerPatrick Palka <ppalka@redhat.com>
Thu, 20 Feb 2020 19:06:23 +0000 (14:06 -0500)
commit6e63438a0d7085e508d82063af2f04d26fa46494
tree023ca2b24d93258d073faea14ad2786cdf10ce23
parent5586e5060fb6a30ade7a7ef854c21bb89b7065c9
libstdc++: Fix capturing of lvalue references in_RangeAdaptor::operator()

This fixes a dangling-reference issue with views::split and other multi-argument
adaptors that may take its extra arguments by reference.

When creating the _RangeAdaptorClosure in _RangeAdaptor::operator(), we
currently capture all provided arguments by value.  When we then use the
_RangeAdaptorClosure and call it with a range, as in e.g.

    v = views::split(p)(range),

we forward the range and the captures to the underlying adaptor routine.  But
then when the temporary _RangeAdaptorClosure goes out of scope, the by-value
captures get destroyed and the references to these captures in the resulting view
become dangling.

This patch fixes this problem by capturing lvalue references by reference in
_RangeAdaptorClosure::operator(), and then forwarding the captures appropriately
to the underlying adaptor routine.

libstdc++-v3/ChangeLog:

* include/std/ranges (views::__adaptor::__maybe_refwrap): New utility
function.
(views::__adaptor::_RangeAdaptor::operator()): Add comments.  Use
__maybe_refwrap to capture lvalue references by reference, and then use
unwrap_reference_t to forward the by-reference captures as references.
* testsuite/std/ranges/adaptors/split.cc: Augment test.
* testsuite/std/ranges/adaptors/split_neg.cc: New test.
libstdc++-v3/ChangeLog
libstdc++-v3/include/std/ranges
libstdc++-v3/testsuite/std/ranges/adaptors/split.cc
libstdc++-v3/testsuite/std/ranges/adaptors/split_neg.cc [new file with mode: 0644]