From patchwork Sun Nov 13 22:55:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ville Voutilainen X-Patchwork-Id: 694289 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tH8Bv6mB2z9syB for ; Mon, 14 Nov 2016 09:55:47 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="MTlT1wJA"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:from:date:message-id :subject:to:content-type; q=dns; s=default; b=sbXXjyKlxMz+LNXNPL 9rQo0W5hgzW6pRkcrfBOTMAKQapQh5wyH+VUxwJehOTb1OTV1w7MknYfMfGkSk2t aLRVLgd1vPNVMT0Yuvt8WLKlTa48lZRsY5cfOlQDzbqHDsCQmiuVa/yQEsRAhlET 0BmitAUd3wMmNAeC4I15/QlJI= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:from:date:message-id :subject:to:content-type; s=default; bh=HsiVSTyHoRg7zyuBB1drCPRo Jdo=; b=MTlT1wJAKeNUWXw5u4Sq2V1tFzyItScyCLAsVmzm7ldBgsp+uOGRoN3H 2iVjzdfyNIDC8t0IlQ6laa+WjR/mn+9+s/kuIg+otd6Nz32fdQdrIGcAspsregPw /Wl+MG6iBVcWCnBtagwy/VdJ5dMuMMe6Y6HMK76w/WAlYRXwR1U= Received: (qmail 41966 invoked by alias); 13 Nov 2016 22:55:26 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 41945 invoked by uid 89); 13 Nov 2016 22:55:25 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.0 required=5.0 tests=AWL, BAYES_50, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=no version=3.3.2 spammy=uba, poisoned, ville.voutilainen@gmail.com, villevoutilainengmailcom X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-vk0-f49.google.com Received: from mail-vk0-f49.google.com (HELO mail-vk0-f49.google.com) (209.85.213.49) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 13 Nov 2016 22:55:15 +0000 Received: by mail-vk0-f49.google.com with SMTP id 137so51719140vkl.0; Sun, 13 Nov 2016 14:55:14 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to; bh=rbqkV/cChRxG2t3wQTKh/1R/iM6fj5k4y10kbIFHf+w=; b=Mf1WrNB8bDbQV4YVIMIBzK76e0i6xXHkDyhlHCx+sA3hTcKo+ZFe7fB4/SF2hR81v/ FKBPnu+5/ALHsMUOg/kWcAWxEmAWM6wGC3GPiBiuaWWnrBQ4KAQWS5BnnZvlNRhecHlj bc4lYHmLqwkavlJuO3PL9ZmH6ObPdprltK2+tAtJfaZNDGneSzeTniRwAC/laHu3EH5X ys4s8gyZtlZOzD6leLz0KKv1dJMTsm1+hI7aSl18y+FTc7DhRTWs+95HvtwxQOayghLf 42gIDufIjjT3qp8Ldfe8p8/h+IFe8VaY3zzugspEB9/He8ivMNRV69IfhuqxmL7h9VT7 /qeQ== X-Gm-Message-State: ABUngvcoxExyAZf0oZ1rGwWS3d3A+NW9CvKh+jWDWvaz1PuoJQFnco4dfGhf/NUWXS6Z1okDNAgAP9pTuWX2GQ== X-Received: by 10.31.81.198 with SMTP id f189mr6969744vkb.160.1479077713189; Sun, 13 Nov 2016 14:55:13 -0800 (PST) MIME-Version: 1.0 Received: by 10.103.48.213 with HTTP; Sun, 13 Nov 2016 14:55:12 -0800 (PST) In-Reply-To: References: From: Ville Voutilainen Date: Mon, 14 Nov 2016 00:55:12 +0200 Message-ID: Subject: Re: [v3 PATCH] Implement P0513R0, Poisoning the Hash. To: "gcc-patches@gcc.gnu.org" , "libstdc++" On 14 November 2016 at 00:49, Ville Voutilainen wrote: > On 14 November 2016 at 00:48, Ville Voutilainen > wrote: >> Tested on Linux-x64. > > > Ah, negative tests incomplete, sending a follow-up soon... Here: 2016-11-13 Ville Voutilainen Implement P0513R0, Poisoning the Hash. * include/bits/functional_hash.h (__poison_hash): New. * include/bits/unique_ptr.h (hash>): Derive from __poison_hash. * include/std/optional (hash>): Likewise. * include/std/variant (hash>): 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. diff --git a/libstdc++-v3/include/bits/functional_hash.h b/libstdc++-v3/include/bits/functional_hash.h index def35f5..dc09683 100644 --- a/libstdc++-v3/include/bits/functional_hash.h +++ b/libstdc++-v3/include/bits/functional_hash.h @@ -57,6 +57,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct hash; + template + struct __poison_hash + { + private: + // Private rather than deleted to be non-trivially-copyable. + __poison_hash(__poison_hash&&); + ~__poison_hash(); + }; + + template + struct __poison_hash<_Tp, __void_t()(declval<_Tp>()))>> + { + }; + // Helper struct for SFINAE-poisoning non-enum types. template::value> struct __hash_enum diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index 996c9ea..f9ec60f 100644 --- a/libstdc++-v3/include/bits/unique_ptr.h +++ b/libstdc++-v3/include/bits/unique_ptr.h @@ -36,6 +36,7 @@ #include #include #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -763,7 +764,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// std::hash specialization for unique_ptr. template struct hash> - : public __hash_base> + : public __hash_base>, + private __poison_hash::pointer> { size_t operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index f272876..69aa54d 100644 --- a/libstdc++-v3/include/std/optional +++ b/libstdc++-v3/include/std/optional @@ -990,7 +990,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Hash. template - struct hash> + struct hash> : private __poison_hash> { using result_type = size_t; using argument_type = optional<_Tp>; diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 314f5f2..004d667 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -41,6 +41,7 @@ #include #include #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -1337,6 +1338,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct hash> + : private __poison_hash>... { using result_type = size_t; using argument_type = variant<_Types...>; diff --git a/libstdc++-v3/testsuite/20_util/optional/hash.cc b/libstdc++-v3/testsuite/20_util/optional/hash.cc new file mode 100644 index 0000000..294a617 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/hash.cc @@ -0,0 +1,38 @@ +// { 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 +// . + +#include +#include + +class S{}; // No hash specialization + +template +auto f(int) -> decltype(std::hash>(), std::true_type()); + +template +auto f(...) -> decltype(std::false_type()); + +static_assert(!decltype(f(0))::value, ""); + +int main() +{ + int x = 42; + std::optional x2 = 42; + VERIFY(std::hash()(x) == std::hash>()(x2)); +} diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc index 9d24826..e9655f1 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc @@ -42,10 +42,10 @@ void f() std::unique_ptr 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 uba(nullptr, b); std::unique_ptr uda(nullptr, d); uba = std::move(uda); // { dg-error "no match" } -// { dg-error "no type" "" { target *-*-* } 539 } +// { dg-error "no type" "" { target *-*-* } 540 } } diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc index a0f77c0..3e6f41b 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc @@ -39,7 +39,7 @@ test07() std::unique_ptr cA3(p); // { dg-error "no matching function" } std::unique_ptr vA3(p); // { dg-error "no matching function" } std::unique_ptr cvA3(p); // { dg-error "no matching function" } - // { dg-error "no type" "" { target *-*-* } 447 } + // { dg-error "no type" "" { target *-*-* } 448 } } template diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/hash/1.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/hash/1.cc index 6fc4fdc..ae73a43 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/hash/1.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/hash/1.cc @@ -21,6 +21,29 @@ #include #include +#include + +// User-defined pointer type that throws if a null pointer is dereferenced. +template +struct Pointer : __gnu_test::PointerBase, T> +{ +}; + +template +struct PointerDeleter : std::default_delete +{ + typedef Pointer pointer; + void operator()(pointer) const; +}; + +template +auto f(int) -> decltype(std::hash>>(), std::true_type()); + +template +auto f(...) -> decltype(std::false_type()); + +static_assert(!decltype(f>(0))::value, ""); void test01() { diff --git a/libstdc++-v3/testsuite/20_util/variant/hash.cc b/libstdc++-v3/testsuite/20_util/variant/hash.cc new file mode 100644 index 0000000..74f97ed --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/variant/hash.cc @@ -0,0 +1,38 @@ +// { 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 +// . + +#include +#include + +class S{}; // No hash specialization + +template +auto f(int) -> decltype(std::hash>(), std::true_type()); + +template +auto f(...) -> decltype(std::false_type()); + +static_assert(!decltype(f(0))::value, ""); + +int main() +{ + int x = 42; + std::variant x2 = 42; + VERIFY(std::hash()(x) == std::hash>()(x2)); +}