Protect allocator-overloads of tuple-from-tuple constructors from cases that would...
authorVille Voutilainen <ville.voutilainen@gmail.com>
Sun, 5 Jun 2016 17:39:10 +0000 (20:39 +0300)
committerVille Voutilainen <ville@gcc.gnu.org>
Sun, 5 Jun 2016 17:39:10 +0000 (20:39 +0300)
Protect allocator-overloads of tuple-from-tuple constructors
from cases that would create dangling references.
* include/std/tuple (tuple(allocator_arg_t, const _Alloc&,
  const tuple<_UElements...>&), tuple(allocator_arg_t, const _Alloc&,
  tuple<_UElements...>&&)): Add a check for _NonNestedTuple.
* testsuite/20_util/tuple/cons/nested_tuple_construct.cc: Adjust.

From-SVN: r237106

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/tuple
libstdc++-v3/testsuite/20_util/tuple/cons/nested_tuple_construct.cc

index 488af9f7da88023766c1b44d49b55c1341da40e8..8ff4d16d0e3ccdb73e6c419c6d0ccd94861a42bb 100644 (file)
@@ -1,3 +1,12 @@
+2016-06-05  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       Protect allocator-overloads of tuple-from-tuple constructors
+       from cases that would create dangling references.
+       * include/std/tuple (tuple(allocator_arg_t, const _Alloc&,
+       const tuple<_UElements...>&), tuple(allocator_arg_t, const _Alloc&,
+       tuple<_UElements...>&&)): Add a check for _NonNestedTuple.
+       * testsuite/20_util/tuple/cons/nested_tuple_construct.cc: Adjust.
+
 2016-05-29  Gerald Pfeifer  <gerald@pfeifer.com>
 
        * doc/xml/manual/backwards_compatibility.xml: Adjust
index ea887932072507d6a476537399b06c2370fc5d48..17c820490300a0c180e90fa4f31d2eb6ed6b2176 100644 (file)
@@ -769,11 +769,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
        : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
 
-      template<typename _Alloc, typename... _UElements, typename
+      template<typename _Alloc, typename _Dummy = void,
+              typename... _UElements, typename
         enable_if<_TMCT<_UElements...>::template
                     _ConstructibleTuple<_UElements...>()
                   && _TMCT<_UElements...>::template
-                    _ImplicitlyConvertibleTuple<_UElements...>(),
+                    _ImplicitlyConvertibleTuple<_UElements...>()
+                  && _TNTC<_Dummy>::template
+                    _NonNestedTuple<tuple<_UElements...>&&>(),
         bool>::type=true>
        tuple(allocator_arg_t __tag, const _Alloc& __a,
              const tuple<_UElements...>& __in)
@@ -781,11 +784,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                     static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
        { }
 
-      template<typename _Alloc, typename... _UElements, typename
+      template<typename _Alloc, typename _Dummy = void,
+              typename... _UElements, typename
         enable_if<_TMCT<_UElements...>::template
                     _ConstructibleTuple<_UElements...>()
                   && !_TMCT<_UElements...>::template
-                    _ImplicitlyConvertibleTuple<_UElements...>(),
+                    _ImplicitlyConvertibleTuple<_UElements...>()
+                  && _TNTC<_Dummy>::template
+                    _NonNestedTuple<tuple<_UElements...>&&>(),
         bool>::type=false>
        explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
              const tuple<_UElements...>& __in)
@@ -793,11 +799,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                     static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
        { }
 
-      template<typename _Alloc, typename... _UElements, typename
+      template<typename _Alloc, typename _Dummy = void,
+              typename... _UElements, typename
         enable_if<_TMCT<_UElements...>::template
                     _MoveConstructibleTuple<_UElements...>()
                   && _TMCT<_UElements...>::template
-                    _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+                    _ImplicitlyMoveConvertibleTuple<_UElements...>()
+                  && _TNTC<_Dummy>::template
+                    _NonNestedTuple<tuple<_UElements...>&&>(),
         bool>::type=true>
        tuple(allocator_arg_t __tag, const _Alloc& __a,
              tuple<_UElements...>&& __in)
@@ -805,11 +814,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                     static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
        { }
 
-      template<typename _Alloc, typename... _UElements, typename
+      template<typename _Alloc, typename _Dummy = void,
+              typename... _UElements, typename
         enable_if<_TMCT<_UElements...>::template
                     _MoveConstructibleTuple<_UElements...>()
                   && !_TMCT<_UElements...>::template
-                    _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+                    _ImplicitlyMoveConvertibleTuple<_UElements...>()
+                  && _TNTC<_Dummy>::template
+                    _NonNestedTuple<tuple<_UElements...>&&>(),
         bool>::type=false>
        explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
              tuple<_UElements...>&& __in)
index 39a4f73c1d450504567fed733fb409a5d79579c8..7f6423913d8f978c433728ebbafb7d1aded93b08 100644 (file)
@@ -63,6 +63,32 @@ void f3()
   std::tuple<std::tuple<X>> t3{std::move(t2)};
 }
 
+void f4()
+{
+  std::allocator<X> a;
+  X v;
+  std::tuple<X> t1{std::allocator_arg, a, v};
+  std::tuple<std::tuple<X>&&> t2{std::allocator_arg, a, std::move(t1)};
+  std::tuple<std::tuple<X>> t3{std::allocator_arg, a, std::move(t2)};
+}
+
+void f5()
+{
+  std::allocator<X> a;
+  X v;
+  std::tuple<X> t1{std::allocator_arg, a, std::move(v)};
+  std::tuple<std::tuple<X>&&> t2{std::allocator_arg, a, std::move(t1)};
+  std::tuple<std::tuple<X>> t3{std::allocator_arg, a, std::move(t2)};
+}
+
+void f6()
+{
+  std::allocator<X> a;
+  std::tuple<X> t1{std::allocator_arg, a, X{}};
+  std::tuple<std::tuple<X>&&> t2{std::allocator_arg, a, std::move(t1)};
+  std::tuple<std::tuple<X>> t3{std::allocator_arg, a, std::move(t2)};
+}
+
 int main()
 {
   f();
@@ -74,4 +100,13 @@ int main()
   f3();
   VERIFY(result == "DefMoveDtorMoveDtorDtor");
   result = "";
+  f4();
+  VERIFY(result == "DefCopyMoveDtorDtorDtor");
+  result = "";
+  f5();
+  VERIFY(result == "DefMoveMoveDtorDtorDtor");
+  result = "";
+  f6();
+  VERIFY(result == "DefMoveDtorMoveDtorDtor");
+  result = "";
 }