commit 2e75149f402d242310ba53b8d31ef38df0d17ed1
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Sat Oct 15 19:06:09 2016 +0100
PR77987 Fix unique_ptr<T[], D>::reset(U) for T != U
PR libstdc++/77987
* include/bits/unique_ptr.h (unique_ptr<T[], D>::reset<U>(U)): Copy
value to pointer of the correct type to swap, to support conversions
allowed by LWG 2118 / N4089.
* testsuite/20_util/unique_ptr/assign/assign_neg.cc: Move test for
incompatible deleters from ...
* testsuite/20_util/unique_ptr/assign/cv_qual.cc: ... here.
* testsuite/20_util/unique_ptr/modifiers/cv_qual.cc: Move tests for
incompatible pointers to ...
* testsuite/20_util/unique_ptr/modifiers/reset_neg.cc: ... here. Move
destructor definition to base class. Test for invalid derived-to-base
conversion.
@@ -610,10 +610,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
reset(_Up __p) noexcept
{
+ pointer __ptr = __p;
using std::swap;
- swap(std::get<0>(_M_t), __p);
- if (__p != nullptr)
- get_deleter()(__p);
+ swap(std::get<0>(_M_t), __ptr);
+ if (__ptr != nullptr)
+ get_deleter()(__ptr);
}
void reset(nullptr_t = nullptr) noexcept
@@ -48,4 +48,25 @@ test03()
std::unique_ptr<int[2]> p2 = p1; // { dg-error "deleted" }
}
+struct base_pointer { operator base*() const { return nullptr; } };
+
+template<typename T>
+struct deleter
+{
+ deleter() = default;
+ template<typename U>
+ deleter(const deleter<U>) { }
+ typedef T pointer;
+ void operator()(T) const { }
+};
+
+void
+test04()
+{
+ // Disallow conversions from incompatible deleter
+ std::unique_ptr<derived[], deleter<base_pointer>> p;
+ std::unique_ptr<base[], deleter<base*>> upA;
+ upA = std::move(p); // { dg-error "no match" }
+}
+
// { dg-prune-output "include" }
@@ -65,26 +65,3 @@ test03()
std::unique_ptr<const volatile A[]> cvA;
cvA = std::move(upA);
}
-
-struct A_pointer { operator A*() const { return nullptr; } };
-
-template<typename T>
-struct deleter
-{
- deleter() = default;
- template<typename U>
- deleter(const deleter<U>) { }
- typedef T pointer;
- void operator()(T) const { }
-};
-
-void
-test04()
-{
- // Disallow conversions from incompatible deleter
- std::unique_ptr<B[], deleter<A_pointer>> p;
- std::unique_ptr<A[], deleter<A*>> upA;
- upA = std::move(p); // { dg-error "no match" }
- // { dg-error "no type" "" { target *-*-* } 537 }
- // { dg-error "no matching function" "" { target *-*-* } 614 }
-}
@@ -86,15 +86,4 @@ test07()
vA2.reset((A*)p);
std::unique_ptr<const volatile A[]> cvA2;
cvA2.reset((A*)p);
- // Disallow conversions from user-defined pointer-like types
- // for the array version
- std::unique_ptr<A[]> upA3;
- upA3.reset(p); // { dg-error "no matching function" }
- std::unique_ptr<const A[]> cA3;
- cA3.reset(p); // { dg-error "no matching function" }
- std::unique_ptr<volatile A[]> vA3;
- vA3.reset(p); // { dg-error "no matching function" }
- std::unique_ptr<const volatile A[]> cvA3;
- cvA3.reset(p); // { dg-error "no matching function" }
- // { dg-error "no matching function" "" { target *-*-* } 614 }
}
@@ -21,17 +21,37 @@
struct A
{
+ virtual ~A() { }
};
struct B : A
{
- virtual ~B() { }
};
-void test01()
+void
+test01()
{
std::unique_ptr<B[]> up;
- up.reset(new A[3]); // { dg-error "" }
+ up.reset(new A[3]); // { dg-error "no matching function" }
+
+ std::unique_ptr<A[]> up2;
+ up2.reset(new B[3]); // { dg-error "no matching function" }
}
-// { dg-prune-output "include" }
+struct A_pointer { operator A*() const { return nullptr; } };
+
+void
+test02()
+{
+ A_pointer p;
+ // Disallow conversions from user-defined pointer-like types
+ // for the array version
+ std::unique_ptr<A[]> upA3;
+ upA3.reset(p); // { dg-error "no matching function" }
+ std::unique_ptr<const A[]> cA3;
+ cA3.reset(p); // { dg-error "no matching function" }
+ std::unique_ptr<volatile A[]> vA3;
+ vA3.reset(p); // { dg-error "no matching function" }
+ std::unique_ptr<const volatile A[]> cvA3;
+ cvA3.reset(p); // { dg-error "no matching function" }
+}
commit 8e8e806cbdd4581331364153d69d39b5765f8343
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Sat Oct 15 18:56:24 2016 +0100
Implement P0084R2, Emplace return type, for C++17
* doc/xml/manual/status_cxx2017.xml: Update status.
* doc/html/*: Regenerate.
* include/bits/deque.tcc (deque::emplace_front, deque::emplace_back):
Return a reference in C++17 mode.
* include/bits/forward_list.h (forward_list::emplace_front): Likewise.
* include/bits/stl_bvector.h (vector<bool>::emplace_back): Likewise.
* include/bits/stl_deque.h (deque::emplace_front, deque::emplace_back):
Likewise.
* include/bits/stl_list.h (list::emplace_front, list::emplace_back):
Likewise.
* include/bits/stl_queue.h (queue::emplace): Likewise.
* include/bits/stl_stack.h (stack::emplace): Likewise.
* include/bits/stl_vector.h (vector::emplace_back): Likewise.
* include/bits/vector.tcc (vector::emplace_back): Likewise.
* include/debug/deque (__gnu_debug::deque::emplace_front)
(__gnu_debug::deque::emplace_back): Likewise.
* include/debug/vector (__gnu_debug::vector::emplace_back): Likewise.
* testsuite/23_containers/deque/modifiers/emplace/cxx17_return.cc:
New.
* testsuite/23_containers/forward_list/modifiers/
emplace_cxx17_return.cc: New.
* testsuite/23_containers/list/modifiers/emplace/cxx17_return.cc: New.
* testsuite/23_containers/queue/members/emplace_cxx17_return.cc: New.
* testsuite/23_containers/stack/members/emplace_cxx17_return.cc: New.
* testsuite/23_containers/vector/bool/emplace_cxx17_return.cc: New.
* testsuite/23_containers/vector/modifiers/emplace/cxx17_return.cc:
New.
@@ -542,14 +542,13 @@ Feature-testing recommendations for C++</link>.
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry> Emplace return type </entry>
<entry>
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0084r2.pdf">
P0084R2
</link>
</entry>
- <entry align="center"> No </entry>
+ <entry align="center"> 7 </entry>
<entry/>
</row>
@@ -129,7 +129,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<typename _Tp, typename _Alloc>
template<typename... _Args>
+#if __cplusplus > 201402L
+ typename deque<_Tp, _Alloc>::reference
+#else
void
+#endif
deque<_Tp, _Alloc>::
emplace_front(_Args&&... __args)
{
@@ -142,11 +146,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
else
_M_push_front_aux(std::forward<_Args>(__args)...);
+#if __cplusplus > 201402L
+ return front();
+#endif
}
template<typename _Tp, typename _Alloc>
template<typename... _Args>
+#if __cplusplus > 201402L
+ typename deque<_Tp, _Alloc>::reference
+#else
void
+#endif
deque<_Tp, _Alloc>::
emplace_back(_Args&&... __args)
{
@@ -160,6 +171,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
else
_M_push_back_aux(std::forward<_Args>(__args)...);
+#if __cplusplus > 201402L
+ return back();
+#endif
}
#endif
@@ -797,10 +797,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* and references.
*/
template<typename... _Args>
- void
+#if __cplusplus > 201402L
+ reference
+#else
+ void
+#endif
emplace_front(_Args&&... __args)
- { this->_M_insert_after(cbefore_begin(),
- std::forward<_Args>(__args)...); }
+ {
+ this->_M_insert_after(cbefore_begin(),
+ std::forward<_Args>(__args)...);
+#if __cplusplus > 201402L
+ return front();
+#endif
+ }
/**
* @brief Add data to the front of the %forward_list.
@@ -1056,9 +1056,18 @@ template<typename _Alloc>
#if __cplusplus >= 201103L
template<typename... _Args>
+#if __cplusplus > 201402L
+ reference
+#else
void
+#endif
emplace_back(_Args&&... __args)
- { push_back(bool(__args...)); }
+ {
+ push_back(bool(__args...));
+#if __cplusplus > 201402L
+ return back();
+#endif
+ }
template<typename... _Args>
iterator
@@ -1519,7 +1519,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ emplace_front(std::move(__x)); }
template<typename... _Args>
- void
+#if __cplusplus > 201402L
+ reference
+#else
+ void
+#endif
emplace_front(_Args&&... __args);
#endif
@@ -1552,7 +1556,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ emplace_back(std::move(__x)); }
template<typename... _Args>
- void
+#if __cplusplus > 201402L
+ reference
+#else
+ void
+#endif
emplace_back(_Args&&... __args);
#endif
@@ -1069,9 +1069,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ this->_M_insert(begin(), std::move(__x)); }
template<typename... _Args>
- void
+#if __cplusplus > 201402L
+ reference
+#else
+ void
+#endif
emplace_front(_Args&&... __args)
- { this->_M_insert(begin(), std::forward<_Args>(__args)...); }
+ {
+ this->_M_insert(begin(), std::forward<_Args>(__args)...);
+#if __cplusplus > 201402L
+ return front();
+#endif
+ }
#endif
/**
@@ -1110,9 +1119,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ this->_M_insert(end(), std::move(__x)); }
template<typename... _Args>
- void
+#if __cplusplus > 201402L
+ reference
+#else
+ void
+#endif
emplace_back(_Args&&... __args)
- { this->_M_insert(end(), std::forward<_Args>(__args)...); }
+ {
+ this->_M_insert(end(), std::forward<_Args>(__args)...);
+#if __cplusplus > 201402L
+ return back();
+#endif
+ }
#endif
/**
@@ -247,11 +247,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
push(value_type&& __x)
{ c.push_back(std::move(__x)); }
+#if __cplusplus > 201402L
+ template<typename... _Args>
+ decltype(auto)
+ emplace(_Args&&... __args)
+ { return c.emplace_back(std::forward<_Args>(__args)...); }
+#else
template<typename... _Args>
void
emplace(_Args&&... __args)
{ c.emplace_back(std::forward<_Args>(__args)...); }
#endif
+#endif
/**
* @brief Removes first element.
@@ -223,11 +223,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
push(value_type&& __x)
{ c.push_back(std::move(__x)); }
+#if __cplusplus > 201402L
+ template<typename... _Args>
+ decltype(auto)
+ emplace(_Args&&... __args)
+ { return c.emplace_back(std::forward<_Args>(__args)...); }
+#else
template<typename... _Args>
void
emplace(_Args&&... __args)
{ c.emplace_back(std::forward<_Args>(__args)...); }
#endif
+#endif
/**
* @brief Removes first element.
@@ -960,7 +960,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ emplace_back(std::move(__x)); }
template<typename... _Args>
+#if __cplusplus > 201402L
+ reference
+#else
void
+#endif
emplace_back(_Args&&... __args);
#endif
@@ -87,7 +87,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<typename _Tp, typename _Alloc>
template<typename... _Args>
+#if __cplusplus > 201402L
+ typename vector<_Tp, _Alloc>::reference
+#else
void
+#endif
vector<_Tp, _Alloc>::
emplace_back(_Args&&... __args)
{
@@ -99,6 +103,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
else
_M_realloc_insert(end(), std::forward<_Args>(__args)...);
+#if __cplusplus > 201402L
+ return back();
+#endif
}
#endif
@@ -386,19 +386,33 @@ namespace __debug
{ emplace_back(std::move(__x)); }
template<typename... _Args>
+#if __cplusplus > 201402L
+ reference
+#else
void
+#endif
emplace_front(_Args&&... __args)
{
_Base::emplace_front(std::forward<_Args>(__args)...);
this->_M_invalidate_all();
+#if __cplusplus > 201402L
+ return front();
+#endif
}
template<typename... _Args>
+#if __cplusplus > 201402L
+ reference
+#else
void
+#endif
emplace_back(_Args&&... __args)
{
_Base::emplace_back(std::forward<_Args>(__args)...);
this->_M_invalidate_all();
+#if __cplusplus > 201402L
+ return back();
+#endif
}
template<typename... _Args>
@@ -478,7 +478,11 @@ namespace __debug
{ emplace_back(std::move(__x)); }
template<typename... _Args>
+#if __cplusplus > 201402L
+ deque<_Tp, _Alloc>::reference
+#else
void
+#endif
emplace_back(_Args&&... __args)
{
bool __realloc = this->_M_requires_reallocation(this->size() + 1);
@@ -486,6 +490,9 @@ namespace __debug
if (__realloc)
this->_M_invalidate_all();
this->_M_update_guaranteed_capacity();
+#if __cplusplus > 201402L
+ return back();
+#endif
}
#endif
new file mode 100644
@@ -0,0 +1,49 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++1z } }
+
+#include <deque>
+#include <testsuite_hooks.h>
+
+using test_type = std::deque<int>;
+
+void
+test01()
+{
+ test_type x{1, 2, 3, 4};
+ test_type::reference r = x.emplace_front(0);
+ VERIFY( r == 0 );
+ VERIFY( &r == &x.front() );
+}
+
+void
+test02()
+{
+ test_type x{1, 2, 3, 4};
+ test_type::reference r = x.emplace_back(5);
+ VERIFY( r == 5 );
+ VERIFY( &r == &x.back() );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,39 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++1z } }
+
+#include <forward_list>
+#include <testsuite_hooks.h>
+
+using test_type = std::forward_list<int>;
+
+void
+test01()
+{
+ test_type x{1, 2, 3, 4};
+ test_type::reference r = x.emplace_front(0);
+ VERIFY( r == 0 );
+ VERIFY( &r == &x.front() );
+}
+
+int
+main()
+{
+ test01();
+}
new file mode 100644
@@ -0,0 +1,49 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++1z } }
+
+#include <list>
+#include <testsuite_hooks.h>
+
+using test_type = std::list<int>;
+
+void
+test01()
+{
+ test_type x{1, 2, 3, 4};
+ test_type::reference r = x.emplace_front(0);
+ VERIFY( r == 0 );
+ VERIFY( &r == &x.front() );
+}
+
+void
+test02()
+{
+ test_type x{1, 2, 3, 4};
+ test_type::reference r = x.emplace_back(5);
+ VERIFY( r == 5 );
+ VERIFY( &r == &x.back() );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,39 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++1z } }
+
+#include <queue>
+#include <testsuite_hooks.h>
+
+using test_type = std::queue<int>;
+
+void
+test01()
+{
+ test_type x{ test_type::container_type{1, 2, 3, 4} };
+ test_type::reference r = x.emplace(5);
+ VERIFY( r == 5 );
+ VERIFY( &r == &x.back() );
+}
+
+int
+main()
+{
+ test01();
+}
new file mode 100644
@@ -0,0 +1,39 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++1z } }
+
+#include <stack>
+#include <testsuite_hooks.h>
+
+using test_type = std::stack<int>;
+
+void
+test01()
+{
+ test_type x{ test_type::container_type{1, 2, 3, 4} };
+ test_type::reference r = x.emplace(5);
+ VERIFY( r == 5 );
+ VERIFY( &r == &x.top() );
+}
+
+int
+main()
+{
+ test01();
+}
new file mode 100644
@@ -0,0 +1,38 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++1z } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+using test_type = std::vector<bool>;
+
+void
+test02()
+{
+ test_type x{true, true};
+ test_type::reference r = x.emplace_back(false);
+ VERIFY( r == false );
+}
+
+int
+main()
+{
+ test02();
+}
new file mode 100644
@@ -0,0 +1,39 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++1z } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+using test_type = std::vector<int>;
+
+void
+test02()
+{
+ test_type x{1, 2, 3, 4};
+ test_type::reference r = x.emplace_back(5);
+ VERIFY( r == 5 );
+ VERIFY( &r == &x.back() );
+}
+
+int
+main()
+{
+ test02();
+}