[Bug libstdc++/90388] Disabled hash specialization should not be invocable

2022-03-16 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90388

Jonathan Wakely  changed:

   What|Removed |Added

   Target Milestone|--- |10.0
 Status|NEW |RESOLVED
 Resolution|--- |FIXED

--- Comment #6 from Jonathan Wakely  ---
Fixed since 10.1

[Bug libstdc++/90388] Disabled hash specialization should not be invocable

2019-05-10 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90388

--- Comment #5 from Jonathan Wakely  ---
Fixed on trunk. The noexcept part might be worth backporting.

[Bug libstdc++/90388] Disabled hash specialization should not be invocable

2019-05-10 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90388

--- Comment #4 from Jonathan Wakely  ---
Author: redi
Date: Fri May 10 21:41:16 2019
New Revision: 271078

URL: https://gcc.gnu.org/viewcvs?rev=271078=gcc=rev
Log:
PR libstdc++/90388 fix std::hash> bugs

A disabled specialization should not be callable, so move the function
call operator into a new base class which correctly implements the
disabled hash semantics. For the versioned namespace configuration do
not derive from __poison_hash in the enabled case, as the empty base
class serves no purpose but potentially increases the object size. For
the default configuration that base class must be kept, to preserve
layout.

An enabled specialization should not be unconditionally noexcept,
because the underlying hash object might throw.

PR libstdc++/90388
* include/bits/unique_ptr.h (default_delete, default_delete):
Use _Require for constraints.
(operator>(nullptr_t, const unique_ptr&)): Implement exactly as
per the standard.
(__uniq_ptr_hash): New base class with conditionally-disabled call
operator.
(hash>): Derive from __uniq_ptr_hash.
* testsuite/20_util/default_delete/48631_neg.cc: Adjust dg-error line.
* testsuite/20_util/unique_ptr/hash/90388.cc: New test.

Added:
trunk/libstdc++-v3/testsuite/20_util/unique_ptr/hash/90388.cc
Modified:
trunk/libstdc++-v3/ChangeLog
trunk/libstdc++-v3/include/bits/unique_ptr.h
trunk/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc

[Bug libstdc++/90388] Disabled hash specialization should not be invocable

2019-05-08 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90388

--- Comment #3 from Jonathan Wakely  ---
Alternative patch:

 operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
 { return !(nullptr < __x); }

-  /// std::hash specialization for unique_ptr.
-  template
-struct hash>
-: public __hash_base>,
-private __poison_hash::pointer>
+  template::__enable_hash_call>
+struct __uniq_ptr_hash
 {
   size_t
-  operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
+  operator()(const _Up& __u) const
+  noexcept(noexcept(std::declval&>()(std::declval<_Ptr>(
   {
-   typedef unique_ptr<_Tp, _Dp> _UP;
-   return std::hash()(__u.get());
+   return hash<_Ptr>()(__u.get());
   }
 };

+  template
+struct __uniq_ptr_hash<_Up, _Ptr, false>
+: private __poison_hash<_Ptr>
+{ };
+
+  /// std::hash specialization for unique_ptr.
+  template
+struct hash>
+: public __hash_base>,
+  public __uniq_ptr_hash>
+{ };
+
 #if __cplusplus > 201103L

 #define __cpp_lib_make_unique 201304

[Bug libstdc++/90388] Disabled hash specialization should not be invocable

2019-05-08 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90388

--- Comment #2 from Jonathan Wakely  ---
Patch for both issues:

@@ -830,14 +847,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct hash>
 : public __hash_base>,
-private __poison_hash::pointer>
+  private __poison_hash::pointer>
 {
-  size_t
-  operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
-  {
-   typedef unique_ptr<_Tp, _Dp> _UP;
-   return std::hash()(__u.get());
-  }
+private:
+  using __poison_base
+   = __poison_hash::pointer>;
+  template
+   using __enabled
+ = __and_>,
+  __bool_constant<__poison_base::__enable_hash_call>>;
+
+public:
+  template
+   typename enable_if<__enabled<_Up>::value, size_t>::type
+   operator()(const _Up& __u) const
+   {
+ return std::hash()(__u.get());
+   }
 };

 #if __cplusplus > 201103L

[Bug libstdc++/90388] Disabled hash specialization should not be invocable

2019-05-08 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90388

Jonathan Wakely  changed:

   What|Removed |Added

 Status|UNCONFIRMED |NEW
   Last reconfirmed||2019-05-08
 Ever confirmed|0   |1

--- Comment #1 from Jonathan Wakely  ---
(In reply to Jonathan Wakely from comment #0)
> Also, hash::operator() should not be unconditionally noexcept, because
> (if it is enabled) hash::operator() might throw
> ([util.smartptr.hash] p1).

Here's a testcase for that part, which should exit normally but calls
std::terminate():

#include 

struct D {
  struct pointer { };
  void operator()(pointer) const noexcept { }
};

bool operator==(D::pointer, std::nullptr_t) { return false; }
bool operator!=(D::pointer, std::nullptr_t) { return true; }

namespace std {
  template<> struct hash {
size_t operator()(D::pointer) const { throw 1; }
  };
}

int main()
{
  using UP = std::unique_ptr;
  UP p;
  std::hash h;
  try {
h(p);
  } catch (int) {
  }
}