* include/bits/functional_hash.h (__poison_hash): New.
* include/bits/unique_ptr.h
(hash<unique_ptr<_Tp, _Dp>>): Derive from __poison_hash.
* include/std/optional (hash<optional<_Tp>>): Likewise.
* include/std/variant (hash<variant<_Types...>>): Likewise.
* testsuite/20_util/default_delete/48631_neg.cc: Adjust.
* testsuite/20_util/default_delete/void_neg.cc: Likewise.
* testsuite/20_util/optional/hash.cc: New.
* testsuite/20_util/unique_ptr/assign/48635_neg.cc: Adjust.
* testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc: Adjust.
* testsuite/20_util/unique_ptr/hash/1.cc: Add tests for
poisoned fancy pointer hashes.
* testsuite/20_util/variant/hash.cc: New.
From-SVN: r242402
+2016-11-14 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ Implement P0513R0, Poisoning the Hash.
+ * include/bits/functional_hash.h (__poison_hash): New.
+ * include/bits/unique_ptr.h
+ (hash<unique_ptr<_Tp, _Dp>>): Derive from __poison_hash.
+ * include/std/optional (hash<optional<_Tp>>): Likewise.
+ * include/std/variant (hash<variant<_Types...>>): Likewise.
+ * testsuite/20_util/default_delete/48631_neg.cc: Adjust.
+ * testsuite/20_util/default_delete/void_neg.cc: Likewise.
+ * testsuite/20_util/optional/hash.cc: New.
+ * testsuite/20_util/unique_ptr/assign/48635_neg.cc: Adjust.
+ * testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc: Adjust.
+ * testsuite/20_util/unique_ptr/hash/1.cc: Add tests for
+ poisoned fancy pointer hashes.
+ * testsuite/20_util/variant/hash.cc: New.
+
2016-11-14 Ville Voutilainen <ville.voutilainen@gmail.com>
Implement P0504R0 (Revisiting in-place tag types for
template<typename _Tp>
struct hash;
+ template<typename _Tp, typename = void>
+ struct __poison_hash
+ {
+ private:
+ // Private rather than deleted to be non-trivially-copyable.
+ __poison_hash(__poison_hash&&);
+ ~__poison_hash();
+ };
+
+ template<typename _Tp>
+ struct __poison_hash<_Tp, __void_t<decltype(hash<_Tp>()(declval<_Tp>()))>>
+ {
+ };
+
// Helper struct for SFINAE-poisoning non-enum types.
template<typename _Tp, bool = is_enum<_Tp>::value>
struct __hash_enum
#include <utility>
#include <tuple>
#include <bits/stl_function.h>
+#include <bits/functional_hash.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
/// std::hash specialization for unique_ptr.
template<typename _Tp, typename _Dp>
struct hash<unique_ptr<_Tp, _Dp>>
- : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>
+ : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>,
+ private __poison_hash<typename unique_ptr<_Tp, _Dp>::pointer>
{
size_t
operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
// Hash.
template<typename _Tp>
- struct hash<optional<_Tp>>
+ struct hash<optional<_Tp>> : private __poison_hash<remove_const_t<_Tp>>
{
using result_type = size_t;
using argument_type = optional<_Tp>;
#include <bits/functexcept.h>
#include <bits/move.h>
#include <bits/uses_allocator.h>
+#include <bits/functional_hash.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
template<typename... _Types>
struct hash<variant<_Types...>>
+ : private __poison_hash<remove_const_t<_Types>>...
{
using result_type = size_t;
using argument_type = variant<_Types...>;
D d;
std::default_delete<B[]> db;
typedef decltype(db(&d)) type; // { dg-error "no match" }
-// { dg-error "no type" "" { target *-*-* } 107 }
+// { dg-error "no type" "" { target *-*-* } 108 }
{
std::default_delete<void> d;
d(nullptr); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 73 }
+ // { dg-error "incomplete" "" { target *-*-* } 74 }
}
--- /dev/null
+// { dg-options "-std=gnu++17" }
+
+// Copyright (C) 2016 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 moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <optional>
+#include <testsuite_hooks.h>
+
+class S{}; // No hash specialization
+
+template<class T>
+auto f(int) -> decltype(std::hash<std::optional<T>>(), std::true_type());
+
+template<class T>
+auto f(...) -> decltype(std::false_type());
+
+static_assert(!decltype(f<S>(0))::value, "");
+
+int main()
+{
+ int x = 42;
+ std::optional<int> x2 = 42;
+ VERIFY(std::hash<int>()(x) == std::hash<std::optional<int>>()(x2));
+}
std::unique_ptr<int, D&> ud(nullptr, d);
ub = std::move(ud); // { dg-error "no match" }
ub2 = ud; // { dg-error "no match" }
-// { dg-error "no type" "" { target *-*-* } 288 }
+// { dg-error "no type" "" { target *-*-* } 289 }
std::unique_ptr<int[], B&> uba(nullptr, b);
std::unique_ptr<int[], D&> uda(nullptr, d);
uba = std::move(uda); // { dg-error "no match" }
-// { dg-error "no type" "" { target *-*-* } 539 }
+// { dg-error "no type" "" { target *-*-* } 540 }
}
std::unique_ptr<const A[]> cA3(p); // { dg-error "no matching function" }
std::unique_ptr<volatile A[]> vA3(p); // { dg-error "no matching function" }
std::unique_ptr<const volatile A[]> cvA3(p); // { dg-error "no matching function" }
- // { dg-error "no type" "" { target *-*-* } 447 }
+ // { dg-error "no type" "" { target *-*-* } 448 }
}
template<typename T>
#include <memory>
#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+// User-defined pointer type that throws if a null pointer is dereferenced.
+template<typename T>
+struct Pointer : __gnu_test::PointerBase<Pointer<T>, T>
+{
+};
+
+template<typename T>
+struct PointerDeleter : std::default_delete<T>
+{
+ typedef Pointer<T> pointer;
+ void operator()(pointer) const;
+};
+
+template<class T>
+auto f(int) -> decltype(std::hash<std::unique_ptr<T,
+ PointerDeleter<T>>>(), std::true_type());
+
+template<class T>
+auto f(...) -> decltype(std::false_type());
+
+static_assert(!decltype(f<Pointer<int>>(0))::value, "");
void test01()
{
--- /dev/null
+// { dg-options "-std=gnu++17" }
+
+// Copyright (C) 2016 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 moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <variant>
+#include <testsuite_hooks.h>
+
+class S{}; // No hash specialization
+
+template<class T>
+auto f(int) -> decltype(std::hash<std::variant<T>>(), std::true_type());
+
+template<class T>
+auto f(...) -> decltype(std::false_type());
+
+static_assert(!decltype(f<S>(0))::value, "");
+
+int main()
+{
+ int x = 42;
+ std::variant<int> x2 = 42;
+ VERIFY(std::hash<int>()(x) == std::hash<std::variant<int>>()(x2));
+}