From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id 599513857C4D; Tue, 18 Jan 2022 16:32:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 599513857C4D 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 r12-6691] libstdc++: Fix ambiguous std::pair constructors [PR101124] X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/master X-Git-Oldrev: 50bc6e463b5f0696bc3cb9edd743d09b17309370 X-Git-Newrev: 302343d8dd30e34516f74a61ec758d80a6c4d1db Message-Id: <20220118163213.599513857C4D@sourceware.org> Date: Tue, 18 Jan 2022 16:32:13 +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 Jan 2022 16:32:13 -0000 https://gcc.gnu.org/g:302343d8dd30e34516f74a61ec758d80a6c4d1db commit r12-6691-g302343d8dd30e34516f74a61ec758d80a6c4d1db Author: Jonathan Wakely Date: Tue Jan 18 15:10:06 2022 +0000 libstdc++: Fix ambiguous std::pair constructors [PR101124] The deprecated non-standard std::pair constructors that allow constructing std::pair from an rvalue and a literal zero where not sufficiently constrained. They were viable when constructing std::pair, and that case should work fine using the standard constructors. Replace the constraints on the non-standard constructors so they are only viable in cases that should actually be ill-formed according to the standard. Also rename __null_ptr_constant to __zero_as_null_pointer_constant so it matches the name of the -Wzero-as-null-pointer-constant warning. Also make the text of the deprecated warning describe the problem in more detail. libstdc++-v3/ChangeLog: PR libstdc++/101124 * include/bits/stl_pair.h (pair): Adjust constraints on deprecated constructors accepting literal zero as null pointer constant. Improve wording of deprecated attribute. * testsuite/20_util/pair/cons/99957.cc: Check that deprecated constructors do not cause ambiguities for copyable types. Diff: --- libstdc++-v3/include/bits/stl_pair.h | 85 ++++++++++++++--------- libstdc++-v3/testsuite/20_util/pair/cons/99957.cc | 12 +++- 2 files changed, 62 insertions(+), 35 deletions(-) diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index abf2120b590..8564fd1ae9e 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -462,62 +462,81 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : first(__p.first), second(__p.second) { } #if _GLIBCXX_USE_DEPRECATED +#if defined(__DEPRECATED) +# define _GLIBCXX_DEPRECATED_PAIR_CTOR \ + __attribute__ ((__deprecated__ ("use 'nullptr' instead of '0' to " \ + "initialize std::pair of move-only " \ + "type and pointer"))) +#else +# define _GLIBCXX_DEPRECATED_PAIR_CTOR +#endif + private: /// @cond undocumented // A type which can be constructed from literal zero, but not nullptr - struct __null_ptr_constant + struct __zero_as_null_pointer_constant { - __null_ptr_constant(int __null_ptr_constant::*) { } + __zero_as_null_pointer_constant(int __zero_as_null_pointer_constant::*) + { } template::value>> - __null_ptr_constant(_Tp) = delete; + __zero_as_null_pointer_constant(_Tp) = delete; }; - - // True if type _Up is one of _Tp& or const _Tp& - template - using __is_lvalue_of - = __or_, is_same<_Up, _Tp&>>; - /// @endcond public: // Deprecated extensions to DR 811. + // These allow construction from an rvalue and a literal zero, + // in cases where the standard says the zero should be deduced as int template::value - && _PCCP::template - _DeprConsPair(), + __enable_if_t<__and_<__not_>, + is_pointer<_T2>, + is_constructible<_T1, _U1>, + __not_>, + is_convertible<_U1, _T1>>::value, bool> = true> - _GLIBCXX_DEPRECATED_SUGGEST("nullptr") - constexpr pair(_U1&& __x, __null_ptr_constant) - : first(std::forward<_U1>(__x)), second(nullptr) { } + _GLIBCXX_DEPRECATED_PAIR_CTOR + constexpr + pair(_U1&& __x, __zero_as_null_pointer_constant, ...) + : first(std::forward<_U1>(__x)), second(nullptr) { } template::value - && _PCCP::template - _DeprConsPair(), + __enable_if_t<__and_<__not_>, + is_pointer<_T2>, + is_constructible<_T1, _U1>, + __not_>, + __not_>>::value, bool> = false> - _GLIBCXX_DEPRECATED_SUGGEST("nullptr") - explicit constexpr pair(_U1&& __x, __null_ptr_constant) - : first(std::forward<_U1>(__x)), second(nullptr) { } + _GLIBCXX_DEPRECATED_PAIR_CTOR + explicit constexpr + pair(_U1&& __x, __zero_as_null_pointer_constant, ...) + : first(std::forward<_U1>(__x)), second(nullptr) { } template::value - && _PCCP::template - _DeprConsPair(), + __enable_if_t<__and_, + __not_>, + is_constructible<_T2, _U2>, + __not_>, + is_convertible<_U2, _T2>>::value, bool> = true> - _GLIBCXX_DEPRECATED_SUGGEST("nullptr") - constexpr pair(__null_ptr_constant, _U2&& __y) - : first(nullptr), second(std::forward<_U2>(__y)) { } + _GLIBCXX_DEPRECATED_PAIR_CTOR + constexpr + pair(__zero_as_null_pointer_constant, _U2&& __y, ...) + : first(nullptr), second(std::forward<_U2>(__y)) { } template::value - && _PCCP::template - _DeprConsPair(), + __enable_if_t<__and_, + __not_>, + is_constructible<_T2, _U2>, + __not_>, + __not_>>::value, bool> = false> - _GLIBCXX_DEPRECATED_SUGGEST("nullptr") - explicit pair(__null_ptr_constant, _U2&& __y) - : first(nullptr), second(std::forward<_U2>(__y)) { } + _GLIBCXX_DEPRECATED_PAIR_CTOR + explicit constexpr + pair(__zero_as_null_pointer_constant, _U2&& __y, ...) + : first(nullptr), second(std::forward<_U2>(__y)) { } +#undef _GLIBCXX_DEPRECATED_PAIR_CTOR #endif template v14{0, MoveOnly{}}; // { dg-warning "deprecated" } -pair v15{MoveOnly{}, 0}; // { dg-warning "deprecated" } +pair v14(0, MoveOnly{}); // { dg-warning "deprecated" } +pair v15(MoveOnly{}, 0); // { dg-warning "deprecated" } pair v16 = {0, MoveOnly{}}; // { dg-warning "deprecated" } pair v17 = {MoveOnly{}, 0}; // { dg-warning "deprecated" } + +// PR libstdc++/101124 +// check deprecated constructors don't cause unwanted ambiguities + +std::pair p(0, 0); // { dg-bogus "ambiguous" } + +struct X { } x; +std::pair p2(x, 0); // { dg-bogus "ambiguous" }