diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2020-04-24 00:54:20 +0100 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2020-04-24 00:54:20 +0100 |
commit | d1462b0782555354b4480e1f46498586d5882972 (patch) | |
tree | 5e31e22610f4c0e69c465c88c1bf9dea4ef07d0c /libstdc++-v3 | |
parent | ae962e573ea5063fda7e86f93d9622e64cea9a7e (diff) | |
download | gcc-d1462b0782555354b4480e1f46498586d5882972.zip gcc-d1462b0782555354b4480e1f46498586d5882972.tar.gz gcc-d1462b0782555354b4480e1f46498586d5882972.tar.bz2 |
libstdc++: Fix constructor constraints for std::any (PR 90415)
This removes a non-standard extension to std::any which causes errors
for valid code, due to recursive instantiation of a trait that isn't
supposed to be in the constraints.
It also removes some incorrect constraints on the in_place_type<T>
constructors and emplace members, which were preventing creating a
std::any object with another std::any as the contained value.
2020-04-24 Kamlesh Kumar <kamleshbhalui@gmail.com>
Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/90415
PR libstdc++/92156
* include/std/any (any): Rename template parameters for consistency
with the standard.
(any::_Decay): Rename to _Decay_if_not_any.
(any::any(T&&):: Remove is_constructible from constraints. Remove
non-standard overload.
(any::any(in_place_type_t<T>, Args&&...))
(any::any(in_place_type_t<T>, initializer_list<U>, Args&&...))
(any::emplace(Args&&...))
(any::emplace(initializer_list<U>, Args&&...)):
Use decay_t instead of _Decay.
* testsuite/20_util/any/cons/90415.cc: New test.
* testsuite/20_util/any/cons/92156.cc: New Test.
* testsuite/20_util/any/misc/any_cast_neg.cc: Make dg-error directives
more robust.
* testsuite/20_util/any/modifiers/92156.cc: New test.
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 21 | ||||
-rw-r--r-- | libstdc++-v3/include/std/any | 115 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/any/cons/90415.cc | 64 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/any/cons/92156.cc | 53 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc | 16 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/any/modifiers/92156.cc | 57 |
6 files changed, 255 insertions, 71 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index ecb8617..7b92ba7 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,24 @@ +2020-04-24 Kamlesh Kumar <kamleshbhalui@gmail.com> + Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/90415 + PR libstdc++/92156 + * include/std/any (any): Rename template parameters for consistency + with the standard. + (any::_Decay): Rename to _Decay_if_not_any. + (any::any(T&&):: Remove is_constructible from constraints. Remove + non-standard overload. + (any::any(in_place_type_t<T>, Args&&...)) + (any::any(in_place_type_t<T>, initializer_list<U>, Args&&...)) + (any::emplace(Args&&...)) + (any::emplace(initializer_list<U>, Args&&...)): + Use decay_t instead of _Decay. + * testsuite/20_util/any/cons/90415.cc: New test. + * testsuite/20_util/any/cons/92156.cc: New Test. + * testsuite/20_util/any/misc/any_cast_neg.cc: Make dg-error directives + more robust. + * testsuite/20_util/any/modifiers/92156.cc: New test. + 2020-04-23 Jonathan Wakely <jwakely@redhat.com> * doc/xml/manual/status_cxx2020.xml: Update C++20 status table. diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any index 6b7e68f..e132922 100644 --- a/libstdc++-v3/include/std/any +++ b/libstdc++-v3/include/std/any @@ -105,8 +105,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Manager_internal<_Tp>, _Manager_external<_Tp>>; - template<typename _Tp, typename _Decayed = decay_t<_Tp>> - using _Decay = enable_if_t<!is_same<_Decayed, any>::value, _Decayed>; + template<typename _Tp, typename _VTp = decay_t<_Tp>> + using _Decay_if_not_any = enable_if_t<!is_same_v<_VTp, any>, _VTp>; /// Emplace with an object created from @p __args as the contained object. template <typename _Tp, typename... _Args, @@ -125,10 +125,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void __do_emplace(initializer_list<_Up> __il, _Args&&... __args) { reset(); - _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); + _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); _M_manager = &_Mgr::_S_manage; } + template <typename _Res, typename _Tp, typename... _Args> + using __any_constructible + = enable_if<__and_<is_copy_constructible<_Tp>, + is_constructible<_Tp, _Args...>>::value, + _Res>; + + template <typename _Tp, typename... _Args> + using __any_constructible_t + = typename __any_constructible<bool, _Tp, _Args...>::type; + + template<typename _VTp, typename... _Args> + using __emplace_t + = typename __any_constructible<_VTp&, _VTp, _Args...>::type; + public: // construct/destruct @@ -165,65 +179,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } - template <typename _Res, typename _Tp, typename... _Args> - using __any_constructible = - enable_if<__and_<is_copy_constructible<_Tp>, - is_constructible<_Tp, _Args...>>::value, - _Res>; - - template <typename _Tp, typename... _Args> - using __any_constructible_t = - typename __any_constructible<bool, _Tp, _Args...>::type; - /// Construct with a copy of @p __value as the contained object. - template <typename _ValueType, typename _Tp = _Decay<_ValueType>, - typename _Mgr = _Manager<_Tp>, - __any_constructible_t<_Tp, _ValueType&&> = true, - enable_if_t<!__is_in_place_type<_Tp>::value, bool> = true> - any(_ValueType&& __value) + template <typename _Tp, typename _VTp = _Decay_if_not_any<_Tp>, + typename _Mgr = _Manager<_VTp>, + enable_if_t<is_copy_constructible<_VTp>::value + && !__is_in_place_type<_VTp>::value, bool> = true> + any(_Tp&& __value) : _M_manager(&_Mgr::_S_manage) { - _Mgr::_S_create(_M_storage, std::forward<_ValueType>(__value)); - } - - /// Construct with a copy of @p __value as the contained object. - template <typename _ValueType, typename _Tp = _Decay<_ValueType>, - typename _Mgr = _Manager<_Tp>, - enable_if_t<__and_v<is_copy_constructible<_Tp>, - __not_<is_constructible<_Tp, _ValueType&&>>, - __not_<__is_in_place_type<_Tp>>>, - bool> = false> - any(_ValueType&& __value) - : _M_manager(&_Mgr::_S_manage) - { - _Mgr::_S_create(_M_storage, __value); + _Mgr::_S_create(_M_storage, std::forward<_Tp>(__value)); } /// Construct with an object created from @p __args as the contained object. - template <typename _ValueType, typename... _Args, - typename _Tp = _Decay<_ValueType>, - typename _Mgr = _Manager<_Tp>, - __any_constructible_t<_Tp, _Args&&...> = false> + template <typename _Tp, typename... _Args, typename _VTp = decay_t<_Tp>, + typename _Mgr = _Manager<_VTp>, + __any_constructible_t<_VTp, _Args&&...> = false> explicit - any(in_place_type_t<_ValueType>, _Args&&... __args) + any(in_place_type_t<_Tp>, _Args&&... __args) : _M_manager(&_Mgr::_S_manage) { - _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); + _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); } /// Construct with an object created from @p __il and @p __args as /// the contained object. - template <typename _ValueType, typename _Up, typename... _Args, - typename _Tp = _Decay<_ValueType>, - typename _Mgr = _Manager<_Tp>, - __any_constructible_t<_Tp, initializer_list<_Up>, + template <typename _Tp, typename _Up, typename... _Args, + typename _VTp = decay_t<_Tp>, typename _Mgr = _Manager<_VTp>, + __any_constructible_t<_VTp, initializer_list<_Up>, _Args&&...> = false> explicit - any(in_place_type_t<_ValueType>, - initializer_list<_Up> __il, _Args&&... __args) + any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args) : _M_manager(&_Mgr::_S_manage) { - _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); + _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); } /// Destructor, calls @c reset() @@ -232,7 +220,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // assignments /// Copy the state of another object. - any& operator=(const any& __rhs) + any& + operator=(const any& __rhs) { *this = any(__rhs); return *this; @@ -243,7 +232,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * @post @c !__rhs.has_value() (not guaranteed for other implementations) */ - any& operator=(any&& __rhs) noexcept + any& + operator=(any&& __rhs) noexcept { if (!__rhs.has_value()) reset(); @@ -258,40 +248,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } /// Store a copy of @p __rhs as the contained object. - template<typename _ValueType> - enable_if_t<is_copy_constructible<_Decay<_ValueType>>::value, any&> - operator=(_ValueType&& __rhs) + template<typename _Tp> + enable_if_t<is_copy_constructible<_Decay_if_not_any<_Tp>>::value, any&> + operator=(_Tp&& __rhs) { - *this = any(std::forward<_ValueType>(__rhs)); + *this = any(std::forward<_Tp>(__rhs)); return *this; } /// Emplace with an object created from @p __args as the contained object. - template <typename _ValueType, typename... _Args> - typename __any_constructible<_Decay<_ValueType>&, - _Decay<_ValueType>, _Args&&...>::type + template <typename _Tp, typename... _Args> + __emplace_t<decay_t<_Tp>, _Args...> emplace(_Args&&... __args) { - __do_emplace<_Decay<_ValueType>>(std::forward<_Args>(__args)...); + using _VTp = decay_t<_Tp>; + __do_emplace<_VTp>(std::forward<_Args>(__args)...); any::_Arg __arg; this->_M_manager(any::_Op_access, this, &__arg); - return *static_cast<_Decay<_ValueType>*>(__arg._M_obj); + return *static_cast<_VTp*>(__arg._M_obj); } /// Emplace with an object created from @p __il and @p __args as /// the contained object. - template <typename _ValueType, typename _Up, typename... _Args> - typename __any_constructible<_Decay<_ValueType>&, - _Decay<_ValueType>, - initializer_list<_Up>, - _Args&&...>::type + template <typename _Tp, typename _Up, typename... _Args> + __emplace_t<decay_t<_Tp>, initializer_list<_Up>, _Args&&...> emplace(initializer_list<_Up> __il, _Args&&... __args) { - __do_emplace<_Decay<_ValueType>, _Up>(__il, - std::forward<_Args>(__args)...); + using _VTp = decay_t<_Tp>; + __do_emplace<_VTp, _Up>(__il, std::forward<_Args>(__args)...); any::_Arg __arg; this->_M_manager(any::_Op_access, this, &__arg); - return *static_cast<_Decay<_ValueType>*>(__arg._M_obj); + return *static_cast<_VTp*>(__arg._M_obj); } // modifiers diff --git a/libstdc++-v3/testsuite/20_util/any/cons/90415.cc b/libstdc++-v3/testsuite/20_util/any/cons/90415.cc new file mode 100644 index 0000000..1222623 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/cons/90415.cc @@ -0,0 +1,64 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } + +// Copyright (C) 2020 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/>. + +#include <any> +#include <utility> +#include <tuple> +#include <testsuite_hooks.h> + +void +test01() +{ + // PR libstdc++/90415 + static_assert( std::is_copy_constructible<std::tuple<std::any>>::value ); +} + +struct wrapper +{ + wrapper() = default; + + wrapper(const std::any& t); + + wrapper(const wrapper& w); + + auto& operator=(const std::any& t); + + auto& operator=(const wrapper& w) + { + value = w.value; + return *this; + } + + std::any value; +}; + +void +test02() +{ + // PR libstdc++/91630 + wrapper a, b; + a = b; +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/cons/92156.cc b/libstdc++-v3/testsuite/20_util/any/cons/92156.cc new file mode 100644 index 0000000..d797473 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/cons/92156.cc @@ -0,0 +1,53 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } + +// Copyright (C) 2020 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/>. + +#include <any> +#include <utility> +#include <tuple> +#include <testsuite_hooks.h> + +void +test01() +{ + auto a = std::any(std::in_place_type<std::any>, 5); + VERIFY( std::any_cast<int>(std::any_cast<std::any>(a)) == 5 ); + + auto b = std::any(std::in_place_type<std::any>, {1}); + (void) std::any_cast<std::initializer_list<int>>(std::any_cast<std::any>(b)); +} + +void +test02() +{ + std::any p = std::pair<std::any, std::any>(1, 1); + auto pt = std::any_cast<std::pair<std::any, std::any>>(p); + VERIFY( std::any_cast<int>(pt.first) == 1 ); + VERIFY( std::any_cast<int>(pt.second) == 1 ); + + std::any t = std::tuple<std::any>(1); + auto tt = std::any_cast<std::tuple<std::any>>(t); + VERIFY( std::any_cast<int>(std::get<0>(tt)) == 1 ); +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc index 6a271e8..049815a 100644 --- a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc +++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc @@ -1,5 +1,5 @@ // { dg-options "-std=gnu++17" } -// { dg-do compile } +// { dg-do compile { target c++17 } } // Copyright (C) 2014-2020 Free Software Foundation, Inc. // @@ -26,20 +26,22 @@ using std::any_cast; void test01() { const any y(1); - any_cast<int&>(y); // { dg-error "invalid 'static_cast'" "" { target { *-*-* } } 461 } - // { dg-error "Template argument must be constructible from a const value" "" { target { *-*-* } } 457 } + any_cast<int&>(y); // { dg-error "here" } + // { dg-error "Template argument must be constructible from a const value" "" { target { *-*-* } } 0 } } void test02() { any y(1); - any_cast<int&&>(y); - // { dg-error "Template argument must be constructible from an lvalue" "" { target { *-*-* } } 483 } + any_cast<int&&>(y); // { dg-error "here" } + // { dg-error "Template argument must be constructible from an lvalue" "" { target { *-*-* } } 0 } } void test03() { any y(1); - any_cast<int&>(std::move(y)); // { dg-error "invalid 'static_cast'" "" { target { *-*-* } } 501 } - // { dg-error "Template argument must be constructible from an rvalue" "" { target { *-*-* } } 497 } + any_cast<int&>(std::move(y)); // { dg-error "here" } + // { dg-error "Template argument must be constructible from an rvalue" "" { target { *-*-* } } 0 } } + +// { dg-prune-output "invalid 'static_cast'" } diff --git a/libstdc++-v3/testsuite/20_util/any/modifiers/92156.cc b/libstdc++-v3/testsuite/20_util/any/modifiers/92156.cc new file mode 100644 index 0000000..4a7bc97 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/modifiers/92156.cc @@ -0,0 +1,57 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } + +// Copyright (C) 2020 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/>. + +#include <any> +#include <utility> +#include <tuple> +#include <testsuite_hooks.h> + +void +test01() +{ + std::any a; + a.emplace<std::any>(5); + VERIFY( std::any_cast<int>(std::any_cast<std::any>(a)) == 5 ); + + std::any b; + b.emplace<std::any>({1}); + (void) std::any_cast<std::initializer_list<int>>(std::any_cast<std::any>(b)); +} + +void +test02() +{ + std::any p; + p.emplace<std::pair<std::any, std::any>>(1, 1); + auto pt = std::any_cast<std::pair<std::any, std::any>>(p); + VERIFY( std::any_cast<int>(pt.first) == 1 ); + VERIFY( std::any_cast<int>(pt.second) == 1 ); + + std::any t; + t.emplace<std::tuple<std::any>>(1); + auto tt = std::any_cast<std::tuple<std::any>>(t); + VERIFY( std::any_cast<int>(std::get<0>(tt)) == 1 ); +} + +int main() +{ + test01(); + test02(); +} |