From patchwork Wed Nov 6 15:48:17 2024
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-Patchwork-Submitter: Jonathan Wakely
X-Patchwork-Id: 2007608
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@legolas.ozlabs.org
Authentication-Results: legolas.ozlabs.org;
dkim=pass (1024-bit key;
unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256
header.s=mimecast20190719 header.b=BEFodKDO;
dkim-atps=neutral
Authentication-Results: legolas.ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org
(client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org;
envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;
receiver=patchwork.ozlabs.org)
Received: from server2.sourceware.org (server2.sourceware.org
[IPv6:2620:52:3:1:0:246e:9693:128c])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384)
(No client certificate requested)
by legolas.ozlabs.org (Postfix) with ESMTPS id 4Xk8mB4yQbz1xyW
for ; Thu, 7 Nov 2024 02:50:01 +1100 (AEDT)
Received: from server2.sourceware.org (localhost [IPv6:::1])
by sourceware.org (Postfix) with ESMTP id 25DD83858403
for ; Wed, 6 Nov 2024 15:49:59 +0000 (GMT)
X-Original-To: gcc-patches@gcc.gnu.org
Delivered-To: gcc-patches@gcc.gnu.org
Received: from us-smtp-delivery-124.mimecast.com
(us-smtp-delivery-124.mimecast.com [170.10.133.124])
by sourceware.org (Postfix) with ESMTP id B5F113858D21
for ; Wed, 6 Nov 2024 15:49:23 +0000 (GMT)
DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B5F113858D21
Authentication-Results: sourceware.org;
dmarc=pass (p=none dis=none) header.from=redhat.com
Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com
ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B5F113858D21
Authentication-Results: server2.sourceware.org;
arc=none smtp.remote-ip=170.10.133.124
ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730908167; cv=none;
b=fuqElF+tpFBd9hY5lJpMERgt+bolUgdoBcPolt8wZBEU+/VcVneHrh+cB+6Fw8QulZzLSxPoKNj+hebnywXK7NyQdaHDW/rP0/rbT6R05Ca5LhOmIi8U1kjhEIgtcXsJEQBbCL3ED9DDN8RHyJZa1FoNnZ8eSkN14bbB8NmGloU=
ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key;
t=1730908167; c=relaxed/simple;
bh=roCllVT1yhGite1V4HpNUrMI5drnOKP2cpVG5vAlfYE=;
h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;
b=MsgDYaZROeHZmEYU+wuL9roSmv/5FLhVC95pUo4UdxwGSE7+lFfXyKvNXc/GH+68Ef0RH0dDMIfNB2V9g/nx834e4E+w4fmyY6Kb+5jAzZGPjGXISbbXuhPOcUyFNtXdRqcZ5BPE/M4jpbv1pyyRHElST6CSHZ8I2IQo5vptrt8=
ARC-Authentication-Results: i=1; server2.sourceware.org
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;
s=mimecast20190719; t=1730908163;
h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding;
bh=/n/I1P9EKLwKUnkwKQs7eqEPJRJ24hTrs3wnsDndKSQ=;
b=BEFodKDOrhPfxxyXbYDnpvtDc/nCeXjgIprI0UT12qaKCxDpqiCMExgJbaS47lPmKGlBXn
MnCB/y3Fz2z/AJvjL9DVKmBlcLGx7QacTvcV694OKw+Hq6eq1jYYkDbgD0tVR1I6mhLcPs
QJOuq7No+2D0MU4g3NyRimqZbEZMTg8=
Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com
(ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by
relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,
cipher=TLS_AES_256_GCM_SHA384) id us-mta-180-zDq4DSH6O86KQ8kYKlstlA-1; Wed,
06 Nov 2024 10:49:20 -0500
X-MC-Unique: zDq4DSH6O86KQ8kYKlstlA-1
X-Mimecast-MFC-AGG-ID: zDq4DSH6O86KQ8kYKlstlA
Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com
(mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest
SHA256)
(No client certificate requested)
by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS
id 625B51955D42; Wed, 6 Nov 2024 15:49:19 +0000 (UTC)
Received: from localhost (unknown [10.42.28.185])
by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP
id CD917300018D; Wed, 6 Nov 2024 15:49:18 +0000 (UTC)
From: Jonathan Wakely
To: libstdc++@gcc.gnu.org,
gcc-patches@gcc.gnu.org
Subject: [PATCH] libstdc++: Refactor std::hash specializations
Date: Wed, 6 Nov 2024 15:48:17 +0000
Message-ID: <20241106154917.379971-1-jwakely@redhat.com>
MIME-Version: 1.0
X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4
X-Mimecast-Spam-Score: 0
X-Mimecast-MFC-PROC-ID: qasmcYLC2vPfDR84HQDw4blgoEmbTiUpAKslTFDgSF8_1730908159
X-Mimecast-Originator: redhat.com
X-BeenThere: gcc-patches@gcc.gnu.org
X-Mailman-Version: 2.1.30
Precedence: list
List-Id: Gcc-patches mailing list
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org
This attempts to simplify and clean up our std::hash code. The primary
benefit is improved diagnostics for users when they do something wrong
involving std::hash or unordered containers. An additional benefit is
that for the unstable ABI (--enable-symvers=gnu-versioned-namespace) we
can reduce the memory footprint of several std::hash specializations.
In the current design, __hash_enum is a base class of the std::hash
primary template, but the partial specialization of __hash_enum for
non-enum types is disabled. This means that if a user forgets to
specialize std::hash for their class type (or forgets to use a custom
hash function for unordered containers) they get error messages about
std::__hash_enum not being constructible. This is confusing when there
is no enum type involved: why should users care about __hash_enum not
being constructible if they're not trying to hash enums?
This change makes the std::hash primary template only derive from
__hash_enum when the template argument type is an enum. Otherwise, it
derives directly from a new class template, __hash_not_enabled. This new
class template defines the deleted members that cause a given std::hash
specialization to be a disabled specialization (as per P0513R0). Now
when users try to use a disabled specialization, they get more
descriptive errors that mention __hash_not_enabled instead of
__hash_enum.
Additionally, adjust __hash_base to remove the deprecated result_type
and argument_type typedefs for C++20 and later.
In the current code we use a __poison_hash base class in the std::hash
specializations for std::unique_ptr, std::optional, and std::variant.
The primary template of __poison_hash has deleted special members, which
is used to conditionally disable the derived std::hash specialization.
This can also result in confusing diagnostics, because seeing "poison"
in an enabled specialization is misleading. Only some uses of
__poison_hash actually "poison" anything, i.e. cause a specialization to
be disabled. In other cases it's just an empty base class that does
nothing.
This change removes __poison_hash and changes the std::hash
specializations that were using it to conditionally derive from
__hash_not_enabled instead. When the std::hash specialization is
enabled, there is no more __poison_hash base class. However, to preserve
the ABI properties of those std::hash specializations, we need to
replace __poison_hash with some other empty base class. This is needed
because in the current code std::hash> has
two __poison_hash base classes, which must have unique addresses,
so sizeof(std::hash>) == 2. To preserve
this unfortunate property, a new __hash_empty_base class is used as a
base class to re-introduce du0plicate base classes that increase the
class size. For the unstable ABI we don't use __hash_empty_base so the
std::hash> specializations are always size 1, and
the class hierarchy is much simpler so will compile faster.
Additionally, remove the result_type and argument_type typedefs from all
disabled specializations of std::hash for std::unique_ptr,
std::optional, and std::variant. Those typedefs are useless for disabled
specializations, and although the standard doesn't say they must *not*
be present for disabled specializations, it certainly only requires them
for enabled specializations. Finally, for C++20 the typedefs are also
removed from enabled specializations of std::hash for std::unique_ptr,
std::optional, and std::variant.
libstdc++-v3/ChangeLog:
* doc/xml/manual/evolution.xml: Document removal of nested types
from std::hash specializations.
* doc/html/manual/api.html: Regenerate.
* include/bits/functional_hash.h (__hash_base): Remove
deprecated nested types for C++20.
(__hash_empty_base): Define new class template.
(__is_hash_enabled_for): Define new variable template.
(__poison_hash): Remove.
(__hash_not_enabled): Define new class template.
(__hash_enum): Remove partial specialization for non-enums.
(hash): Derive from __hash_not_enabled for non-enums, instead of
__hash_enum.
* include/bits/unique_ptr.h (__uniq_ptr_hash): Derive from
__hash_base. Conditionally derive from __hash_empty_base.
(__uniq_ptr_hash<>): Remove disabled specialization.
(hash): Do not derive from __hash_base unconditionally.
Conditionally derive from either __uniq_ptr_hash or
__hash_not_enabled.
* include/std/optional (__optional_hash_call_base): Remove.
(__optional_hash): Define new class template.
(hash): Derive from either
(hash): Conditionally derive from either __optional_hash or
__hash_not_enabled. Remove nested typedefs.
* include/std/variant (_Base_dedup): Replace __poison_hash with
__hash_empty_base.
(__variant_hash_call_base_impl): Remove.
(__variant_hash): Define new class template.
(hash): Conditionally derive from either __variant_hash or
__hash_not_enabled. Remove nested typedefs.
* testsuite/20_util/optional/hash.cc: Check whether nested types
are present.
* testsuite/20_util/variant/hash.cc: Likewise.
* testsuite/20_util/optional/hash_abi.cc: New test.
* testsuite/20_util/unique_ptr/hash/abi.cc: New test.
* testsuite/20_util/unique_ptr/hash/types.cc: New test.
* testsuite/20_util/variant/hash_abi.cc: New test.
---
Tested x86_64-linux.
Also available for review at:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/16
libstdc++-v3/doc/html/manual/api.html | 3 +
libstdc++-v3/doc/xml/manual/evolution.xml | 5 ++
libstdc++-v3/include/bits/functional_hash.h | 47 +++++++-------
libstdc++-v3/include/bits/unique_ptr.h | 18 +++---
libstdc++-v3/include/std/optional | 26 ++++----
libstdc++-v3/include/std/variant | 41 ++++++------
.../testsuite/20_util/optional/hash.cc | 33 ++++++++++
.../testsuite/20_util/optional/hash_abi.cc | 35 ++++++++++
.../testsuite/20_util/unique_ptr/hash/abi.cc | 64 +++++++++++++++++++
.../20_util/unique_ptr/hash/types.cc | 53 +++++++++++++++
.../testsuite/20_util/variant/hash.cc | 34 ++++++++++
.../testsuite/20_util/variant/hash_abi.cc | 48 ++++++++++++++
12 files changed, 344 insertions(+), 63 deletions(-)
create mode 100644 libstdc++-v3/testsuite/20_util/optional/hash_abi.cc
create mode 100644 libstdc++-v3/testsuite/20_util/unique_ptr/hash/abi.cc
create mode 100644 libstdc++-v3/testsuite/20_util/unique_ptr/hash/types.cc
create mode 100644 libstdc++-v3/testsuite/20_util/variant/hash_abi.cc
diff --git a/libstdc++-v3/doc/html/manual/api.html b/libstdc++-v3/doc/html/manual/api.html
index 2ccfc07b83e..7a4c7d9fe62 100644
--- a/libstdc++-v3/doc/html/manual/api.html
+++ b/libstdc++-v3/doc/html/manual/api.html
@@ -506,4 +506,7 @@ and removed in C++20:
<cstdalign>
,
<cstdbool>
, and
<ctgmath>
.
+
+Nested result_type
and argument_type
removed from
+std::hash
specializations for C++20.