mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-01 15:50:19 +08:00
libstdc++: Fix ambiguous std::pair constructors [PR101124]
The deprecated non-standard std::pair constructors that allow constructing std::pair<move-only-type, pointer-type> from an rvalue and a literal zero where not sufficiently constrained. They were viable when constructing std::pair<copyable-type, pointer-type>, 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.
This commit is contained in:
parent
50bc6e463b
commit
302343d8dd
@ -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<typename _Tp,
|
||||
typename = __enable_if_t<is_null_pointer<_Tp>::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<typename _Up, typename _Tp>
|
||||
using __is_lvalue_of
|
||||
= __or_<is_same<_Up, const _Tp&>, 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<typename _U1,
|
||||
__enable_if_t<!__is_lvalue_of<_U1, _T1>::value
|
||||
&& _PCCP::template
|
||||
_DeprConsPair<true, _U1, nullptr_t>(),
|
||||
__enable_if_t<__and_<__not_<is_reference<_U1>>,
|
||||
is_pointer<_T2>,
|
||||
is_constructible<_T1, _U1>,
|
||||
__not_<is_constructible<_T1, const _U1&>>,
|
||||
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<typename _U1,
|
||||
__enable_if_t<!__is_lvalue_of<_U1, _T1>::value
|
||||
&& _PCCP::template
|
||||
_DeprConsPair<false, _U1, nullptr_t>(),
|
||||
__enable_if_t<__and_<__not_<is_reference<_U1>>,
|
||||
is_pointer<_T2>,
|
||||
is_constructible<_T1, _U1>,
|
||||
__not_<is_constructible<_T1, const _U1&>>,
|
||||
__not_<is_convertible<_U1, _T1>>>::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<typename _U2,
|
||||
__enable_if_t<!__is_lvalue_of<_U2, _T2>::value
|
||||
&& _PCCP::template
|
||||
_DeprConsPair<true, nullptr_t, _U2>(),
|
||||
__enable_if_t<__and_<is_pointer<_T1>,
|
||||
__not_<is_reference<_U2>>,
|
||||
is_constructible<_T2, _U2>,
|
||||
__not_<is_constructible<_T2, const _U2&>>,
|
||||
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<typename _U2,
|
||||
__enable_if_t<!__is_lvalue_of<_U2, _T2>::value
|
||||
&& _PCCP::template
|
||||
_DeprConsPair<false, nullptr_t, _U2>(),
|
||||
__enable_if_t<__and_<is_pointer<_T1>,
|
||||
__not_<is_reference<_U2>>,
|
||||
is_constructible<_T2, _U2>,
|
||||
__not_<is_constructible<_T2, const _U2&>>,
|
||||
__not_<is_convertible<_U2, _T2>>>::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<typename _U1, typename _U2, typename
|
||||
|
@ -22,8 +22,16 @@ struct ExplicitMoveOnly
|
||||
// PR libstdc++/99957
|
||||
// check non-standard constructors are deprecated
|
||||
|
||||
pair<int*, ExplicitMoveOnly> v14{0, MoveOnly{}}; // { dg-warning "deprecated" }
|
||||
pair<ExplicitMoveOnly, int*> v15{MoveOnly{}, 0}; // { dg-warning "deprecated" }
|
||||
pair<int*, ExplicitMoveOnly> v14(0, MoveOnly{}); // { dg-warning "deprecated" }
|
||||
pair<ExplicitMoveOnly, int*> v15(MoveOnly{}, 0); // { dg-warning "deprecated" }
|
||||
|
||||
pair<int*, MoveOnly> v16 = {0, MoveOnly{}}; // { dg-warning "deprecated" }
|
||||
pair<MoveOnly, int*> v17 = {MoveOnly{}, 0}; // { dg-warning "deprecated" }
|
||||
|
||||
// PR libstdc++/101124
|
||||
// check deprecated constructors don't cause unwanted ambiguities
|
||||
|
||||
std::pair<long*, int> p(0, 0); // { dg-bogus "ambiguous" }
|
||||
|
||||
struct X { } x;
|
||||
std::pair<const X, void*> p2(x, 0); // { dg-bogus "ambiguous" }
|
||||
|
Loading…
Reference in New Issue
Block a user