From: Ville Voutilainen Date: Fri, 25 Sep 2015 16:41:45 +0000 (+0300) Subject: Avoid creating dangling references in case of nested tuples X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5e2f2cd5842d2543721a895c64a3b2a553542344;p=gcc.git Avoid creating dangling references in case of nested tuples for tuple constructors that construct from other tuples. 2015-09-25 Ville Voutilainen Avoid creating dangling references in case of nested tuples for tuple constructors that construct from other tuples. * include/std/tuple (_TC::_NonNestedTuple): New. * include/std/tuple (tuple::_TNTC): New. * include/std/tuple (tuple(const tuple<_UElements...>&), tuple(tuple<_UElements...>&&): Use _TNTC. * testsuite/20_util/tuple/cons/nested_tuple_construct.cc: New. From-SVN: r228134 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 24a60508cce..50f6e8b694c 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,13 @@ +2015-09-25 Ville Voutilainen + + Avoid creating dangling references in case of nested tuples + for tuple constructors that construct from other tuples. + * include/std/tuple (_TC::_NonNestedTuple): New. + * include/std/tuple (tuple::_TNTC): New. + * include/std/tuple (tuple(const tuple<_UElements...>&), + tuple(tuple<_UElements...>&&): Use _TNTC. + * testsuite/20_util/tuple/cons/nested_tuple_construct.cc: New. + 2015-09-24 Jonathan Wakely PR libstdc++/67707 diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 59b992a4a06..751d7eb97cc 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -486,6 +486,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __and_...>::value; } + + template + static constexpr bool _NonNestedTuple() + { + return __and_<__not_>, + __not_> + >::value; + } }; template @@ -514,6 +522,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return false; } + + template + static constexpr bool _NonNestedTuple() + { + return true; + } }; /// Primary class template, tuple @@ -599,40 +613,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr tuple(tuple&&) = default; - template using _TNTC = + _TC::value && sizeof...(_Elements) == 1, + _Elements...>; + + template::template _ConstructibleTuple<_UElements...>() && _TMC<_UElements...>::template - _ImplicitlyConvertibleTuple<_UElements...>(), + _ImplicitlyConvertibleTuple<_UElements...>() + && _TNTC<_Dummy>::template + _NonNestedTuple&>(), bool>::type=true> constexpr tuple(const tuple<_UElements...>& __in) : _Inherited(static_cast&>(__in)) { } - template::template _ConstructibleTuple<_UElements...>() && !_TMC<_UElements...>::template - _ImplicitlyConvertibleTuple<_UElements...>(), + _ImplicitlyConvertibleTuple<_UElements...>() + && _TNTC<_Dummy>::template + _NonNestedTuple&>(), bool>::type=false> explicit constexpr tuple(const tuple<_UElements...>& __in) : _Inherited(static_cast&>(__in)) { } - template::template _MoveConstructibleTuple<_UElements...>() && _TMC<_UElements...>::template - _ImplicitlyMoveConvertibleTuple<_UElements...>(), + _ImplicitlyMoveConvertibleTuple<_UElements...>() + && _TNTC<_Dummy>::template + _NonNestedTuple&&>(), bool>::type=true> constexpr tuple(tuple<_UElements...>&& __in) : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } - template::template _MoveConstructibleTuple<_UElements...>() && !_TMC<_UElements...>::template - _ImplicitlyMoveConvertibleTuple<_UElements...>(), + _ImplicitlyMoveConvertibleTuple<_UElements...>() + && _TNTC<_Dummy>::template + _NonNestedTuple&&>(), bool>::type=false> explicit constexpr tuple(tuple<_UElements...>&& __in) : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/nested_tuple_construct.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/nested_tuple_construct.cc new file mode 100644 index 00000000000..32ef3cc0259 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/cons/nested_tuple_construct.cc @@ -0,0 +1,60 @@ +#include +#include +#include + +static std::string result; + +struct X { + int state; // this has to be here + X() { + result += "Def"; + } + + X(X const&) { + result += "Copy"; + } + + X(X&&) { + result += "Move"; + } + + ~X() { + result += "Dtor"; + } +}; + +void f() +{ + X v; + std::tuple t1{v}; + std::tuple&&> t2{std::move(t1)}; + std::tuple> t3{std::move(t2)}; +} + +void f2() +{ + X v; + std::tuple t1{std::move(v)}; + std::tuple&&> t2{std::move(t1)}; + std::tuple> t3{std::move(t2)}; +} + +void f3() +{ + std::tuple t1{X{}}; + std::tuple&&> t2{std::move(t1)}; + std::tuple> t3{std::move(t2)}; +} + +int main() +{ + f(); + VERIFY(result == "DefCopyMoveDtorDtorDtor"); + result = ""; + f2(); + VERIFY(result == "DefMoveMoveDtorDtorDtor"); + result = ""; + f3(); + VERIFY(result == "DefMoveDtorMoveDtorDtor"); + result = ""; +}