From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2100) id 8ECA0384243D; Tue, 18 Aug 2020 01:42:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8ECA0384243D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1597714957; bh=H/jpahPDyaWv95Om3ZX0kz07j8yhdSzgxEB9g5yF5ug=; h=From:To:Subject:Date:From; b=UaMPx3OdDHO2QZn9iZ+bgsEUQC+fg5Ovfocrn71cn5z+q0obbzPzE7oaAad9hHtpb 5z9ufVjWZ8xBWWTsFxSRfY9kwjNuIEAohL3HpUGh/jzUFzsevR2R+QrnTf6YetSUd0 idr3fGX+3Ygxeq+c9cy8D+NTwLPKHL9GNnzKbxxE= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Giuliano Belinassi To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc(refs/users/giulianob/heads/autopar_rebase2)] libstdc++: Remove inheritance from elements in std::tuple X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/users/giulianob/heads/autopar_rebase2 X-Git-Oldrev: 5cd12fbfd32ac7b40a901942471d52d22de81c36 X-Git-Newrev: fcbca3c166d91dac355ff6e917a9c39c7c62bb56 Message-Id: <20200818014237.8ECA0384243D@sourceware.org> Date: Tue, 18 Aug 2020 01:42:37 +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: Tue, 18 Aug 2020 01:42:37 -0000 https://gcc.gnu.org/g:fcbca3c166d91dac355ff6e917a9c39c7c62bb56 commit fcbca3c166d91dac355ff6e917a9c39c7c62bb56 Author: Jonathan Wakely Date: Fri Aug 7 17:13:56 2020 +0100 libstdc++: Remove inheritance from elements in std::tuple This fixes a number of std::tuple bugs by no longer making use of the empty base-class optimization. By using the C++20 [[no_unique_address]] attribute we can always store the element as a data member, while still compressing the layout of tuples containing empty types. Since we no longer use inheritance we could also apply the compression optimization for final types and for tuples of tuples, but doing so would be an ABI break. Using [[no_unique_address]] more liberally for the unstable std::__8 configuration is left for a later date. There may be reasons not to apply the attribute unconditionally, e.g. see the discussion about guaranteed elision in PR 94062. libstdc++-v3/ChangeLog: PR libstdc++/55713 PR libstdc++/71096 PR libstdc++/93147 * include/std/tuple [__has_cpp_attribute(no_unique_address)] (_Head_base): New definition of the partial specialization, using [[no_unique_address]] instead of inheritance. * testsuite/libstdc++-prettyprinters/48362.cc: Adjust expected output. * testsuite/20_util/tuple/comparison_operators/93147.cc: New test. * testsuite/20_util/tuple/creation_functions/55713.cc: New test. * testsuite/20_util/tuple/element_access/71096.cc: New test. Diff: --- libstdc++-v3/include/std/tuple | 53 ++++++++++++++++++++++ .../20_util/tuple/comparison_operators/93147.cc | 36 +++++++++++++++ .../20_util/tuple/creation_functions/55713.cc | 33 ++++++++++++++ .../20_util/tuple/element_access/71096.cc | 30 ++++++++++++ .../testsuite/libstdc++-prettyprinters/48362.cc | 2 +- 5 files changed, 153 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 0dc11768a90..d4a35f0fe7f 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -73,6 +73,58 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool = __empty_not_final<_Head>::value> struct _Head_base; +#if __has_cpp_attribute(no_unique_address) + template + struct _Head_base<_Idx, _Head, true> + { + constexpr _Head_base() + : _M_head_impl() { } + + constexpr _Head_base(const _Head& __h) + : _M_head_impl(__h) { } + + constexpr _Head_base(const _Head_base&) = default; + constexpr _Head_base(_Head_base&&) = default; + + template + constexpr _Head_base(_UHead&& __h) + : _M_head_impl(std::forward<_UHead>(__h)) { } + + _GLIBCXX20_CONSTEXPR + _Head_base(allocator_arg_t, __uses_alloc0) + : _M_head_impl() { } + + template + _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) + : _M_head_impl(allocator_arg, *__a._M_a) { } + + template + _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) + : _M_head_impl(*__a._M_a) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(__uses_alloc0, _UHead&& __uhead) + : _M_head_impl(std::forward<_UHead>(__uhead)) { } + + template + _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) + : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) + { } + + template + _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) + : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { } + + static constexpr _Head& + _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; } + + static constexpr const _Head& + _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; } + + [[no_unique_address]] _Head _M_head_impl; + }; +#else template struct _Head_base<_Idx, _Head, true> : public _Head @@ -119,6 +171,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static constexpr const _Head& _M_head(const _Head_base& __b) noexcept { return __b; } }; +#endif template struct _Head_base<_Idx, _Head, false> diff --git a/libstdc++-v3/testsuite/20_util/tuple/comparison_operators/93147.cc b/libstdc++-v3/testsuite/20_util/tuple/comparison_operators/93147.cc new file mode 100644 index 00000000000..b6c61d5717b --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/comparison_operators/93147.cc @@ -0,0 +1,36 @@ +// 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 +// . + +// { dg-do compile { target c++11 } } + + +#include + +struct A { + bool operator == (A) const { return true; } +}; + +struct B { + bool operator == (B) const { return true; } +}; + +using Tuple = std::tuple; + +bool example(Tuple a, Tuple b) +{ + return a == b; // PR libstdc++/93147 +} diff --git a/libstdc++-v3/testsuite/20_util/tuple/creation_functions/55713.cc b/libstdc++-v3/testsuite/20_util/tuple/creation_functions/55713.cc new file mode 100644 index 00000000000..05a90198fde --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/creation_functions/55713.cc @@ -0,0 +1,33 @@ +// 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 +// . + +// { dg-do compile { target c++11 } } + +#include + +struct A { }; + +void f(A); + +struct B { B(std::tuple); }; + +void f(B); + +void test01() +{ + f(std::make_tuple(A())); // PR libstdc++/55713 +} diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/71096.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/71096.cc new file mode 100644 index 00000000000..6fa882f25d5 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/71096.cc @@ -0,0 +1,30 @@ +// 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 +// . + +// { dg-do compile { target c++11 } } + +#include + +struct A {}; +struct B : std::tuple {}; + +void +test01() +{ + std::tuple t; + std::get<0>(t); // PR libstdc++/71096 +} diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc index 85add53fe5a..f8ff6fba5a7 100644 --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc @@ -29,7 +29,7 @@ main() // { dg-final { note-test t1 {empty std::tuple} } } std::tuple> t2{ "Johnny", 5, {} }; -// { dg-final { regexp-test t2 {std::tuple containing = {\[1\] = "Johnny", \[2\] = 5, \[3\] = {> = empty std::tuple, }}} } } +// { dg-final { regexp-test t2 {std::tuple containing = {\[1\] = "Johnny", \[2\] = 5, \[3\] = empty std::tuple}} } } std::cout << "\n"; return 0; // Mark SPOT