From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id A9F9839ACC0E; Thu, 22 Jul 2021 21:28:56 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A9F9839ACC0E MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r9-9638] libstdc++: Fix constructor constraints for std::any (PR 90415) X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/releases/gcc-9 X-Git-Oldrev: b06478ca4142ca204133351da45691c787314f64 X-Git-Newrev: 14597b680a24b6f7375e4470dea935da9c369feb Message-Id: <20210722212856.A9F9839ACC0E@sourceware.org> Date: Thu, 22 Jul 2021 21:28:56 +0000 (GMT) X-BeenThere: libstdc++-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Jul 2021 21:28:56 -0000 https://gcc.gnu.org/g:14597b680a24b6f7375e4470dea935da9c369feb commit r9-9638-g14597b680a24b6f7375e4470dea935da9c369feb Author: Jonathan Wakely Date: Fri Apr 24 00:54:20 2020 +0100 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 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 Jonathan Wakely 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, Args&&...)) (any::any(in_place_type_t, initializer_list, Args&&...)) (any::emplace(Args&&...)) (any::emplace(initializer_list, 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. (cherry picked from commit d1462b0782555354b4480e1f46498586d5882972) Diff: --- libstdc++-v3/include/std/any | 115 +++++++++------------ libstdc++-v3/testsuite/20_util/any/cons/90415.cc | 64 ++++++++++++ libstdc++-v3/testsuite/20_util/any/cons/92156.cc | 53 ++++++++++ .../testsuite/20_util/any/misc/any_cast_neg.cc | 16 +-- .../testsuite/20_util/any/modifiers/92156.cc | 57 ++++++++++ 5 files changed, 234 insertions(+), 71 deletions(-) diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any index 91c4c1a7cf1..796949c7d4a 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> - using _Decay = enable_if_t::value, _Decayed>; + template> + using _Decay_if_not_any = enable_if_t, _VTp>; /// Emplace with an object created from @p __args as the contained object. template __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 + using __any_constructible + = enable_if<__and_, + is_constructible<_Tp, _Args...>>::value, + _Res>; + + template + using __any_constructible_t + = typename __any_constructible::type; + + template + using __emplace_t + = typename __any_constructible<_VTp&, _VTp, _Args...>::type; + public: // construct/destruct @@ -165,65 +179,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } - template - using __any_constructible = - enable_if<__and_, - is_constructible<_Tp, _Args...>>::value, - _Res>; - - template - using __any_constructible_t = - typename __any_constructible::type; - /// Construct with a copy of @p __value as the contained object. - template , - typename _Mgr = _Manager<_Tp>, - __any_constructible_t<_Tp, _ValueType&&> = true, - enable_if_t::value, bool> = true> - any(_ValueType&& __value) + template , + typename _Mgr = _Manager<_VTp>, + enable_if_t::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 _Mgr = _Manager<_Tp>, - enable_if_t<__and_v, - __not_>, - __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 _Mgr = _Manager<_Tp>, - __any_constructible_t<_Tp, _Args&&...> = false> + template , + 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 _Mgr = _Manager<_Tp>, - __any_constructible_t<_Tp, initializer_list<_Up>, + template , 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 - enable_if_t>::value, any&> - operator=(_ValueType&& __rhs) + template + enable_if_t>::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 __any_constructible<_Decay<_ValueType>&, - _Decay<_ValueType>, _Args&&...>::type + template + __emplace_t, _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 __any_constructible<_Decay<_ValueType>&, - _Decay<_ValueType>, - initializer_list<_Up>, - _Args&&...>::type + template + __emplace_t, 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 00000000000..122262386d3 --- /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 +// . + +#include +#include +#include +#include + +void +test01() +{ + // PR libstdc++/90415 + static_assert( std::is_copy_constructible>::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 00000000000..d797473716d --- /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 +// . + +#include +#include +#include +#include + +void +test01() +{ + auto a = std::any(std::in_place_type, 5); + VERIFY( std::any_cast(std::any_cast(a)) == 5 ); + + auto b = std::any(std::in_place_type, {1}); + (void) std::any_cast>(std::any_cast(b)); +} + +void +test02() +{ + std::any p = std::pair(1, 1); + auto pt = std::any_cast>(p); + VERIFY( std::any_cast(pt.first) == 1 ); + VERIFY( std::any_cast(pt.second) == 1 ); + + std::any t = std::tuple(1); + auto tt = std::any_cast>(t); + VERIFY( std::any_cast(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 d8a52d719db..0c56fce963f 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-2019 Free Software Foundation, Inc. // @@ -26,20 +26,22 @@ using std::any_cast; void test01() { const any y(1); - any_cast(y); // { dg-error "invalid static_cast" "" { target { *-*-* } } 461 } - // { dg-error "Template argument must be constructible from a const value" "" { target { *-*-* } } 457 } + any_cast(y); // { dg-error "here" } + // { dg-error "Template argument must be constructible from a const value" "" { target { *-*-* } } 0 } } void test02() { any y(1); - any_cast(y); - // { dg-error "Template argument must be constructible from an lvalue" "" { target { *-*-* } } 483 } + any_cast(y); // { dg-error "here" } + // { dg-error "Template argument must be constructible from an lvalue" "" { target { *-*-* } } 0 } } void test03() { any y(1); - any_cast(std::move(y)); // { dg-error "invalid static_cast" "" { target { *-*-* } } 501 } - // { dg-error "Template argument must be constructible from an rvalue" "" { target { *-*-* } } 497 } + any_cast(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 00000000000..4a7bc97bb83 --- /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 +// . + +#include +#include +#include +#include + +void +test01() +{ + std::any a; + a.emplace(5); + VERIFY( std::any_cast(std::any_cast(a)) == 5 ); + + std::any b; + b.emplace({1}); + (void) std::any_cast>(std::any_cast(b)); +} + +void +test02() +{ + std::any p; + p.emplace>(1, 1); + auto pt = std::any_cast>(p); + VERIFY( std::any_cast(pt.first) == 1 ); + VERIFY( std::any_cast(pt.second) == 1 ); + + std::any t; + t.emplace>(1); + auto tt = std::any_cast>(t); + VERIFY( std::any_cast(std::get<0>(tt)) == 1 ); +} + +int main() +{ + test01(); + test02(); +}