public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-6691] libstdc++: Fix ambiguous std::pair constructors [PR101124]
@ 2022-01-18 16:32 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2022-01-18 16:32 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:302343d8dd30e34516f74a61ec758d80a6c4d1db

commit r12-6691-g302343d8dd30e34516f74a61ec758d80a6c4d1db
Author: Jonathan Wakely <jwakely@redhat.com>
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<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.

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<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
diff --git a/libstdc++-v3/testsuite/20_util/pair/cons/99957.cc b/libstdc++-v3/testsuite/20_util/pair/cons/99957.cc
index 82ec54ca1d8..8432856d0b0 100644
--- a/libstdc++-v3/testsuite/20_util/pair/cons/99957.cc
+++ b/libstdc++-v3/testsuite/20_util/pair/cons/99957.cc
@@ -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" }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-01-18 16:32 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-18 16:32 [gcc r12-6691] libstdc++: Fix ambiguous std::pair constructors [PR101124] Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).