From patchwork Tue May 21 19:36:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1937521 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=KVNj8/dh; 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 4VkPp03sqDz20PS for ; Wed, 22 May 2024 05:36:56 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6EB6E385B529 for ; Tue, 21 May 2024 19:36:54 +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.129.124]) by sourceware.org (Postfix) with ESMTPS id B4BAD3858D1E for ; Tue, 21 May 2024 19:36:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B4BAD3858D1E 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 B4BAD3858D1E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1716320197; cv=none; b=SNp+jFQsXH1VD+J1mbNFU4PNYp4wPC+zqbOCghDXqPgpJsJTQ5La4VoYCEA3uH8WoBx2xx+zw1+UsM8mdKtxbSE07lpoa+4xXnhLtIUCe0KjIJBr7IhXrfVZVUNXeScVgEEhwA5jRc0j3hkJV5z14nH3qAkPQorqOsspz647Kis= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1716320197; c=relaxed/simple; bh=DLaNDGS8eq4lTpijD+Z/nPPNj+jfLz+7PYRrupkXccU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=lvffhEPBmsI04sbsKU/tvxnV/G+LCQa1J71uYuv7CWhPYPqgocsOR7sxtzkcobdAmb+qklZv1fdBCY6EoXG4FV3wD5FRvcXe84fYgMiuyFU/Z9reBB1gW4SHn86xcs5nkM8+tPGWaS1hFVMlHpXpceb2BfeJy+844CHSi2C03TU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1716320195; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Ustz+glglc5DJtPKmYBunhEd8PemFyPnTq9PZEXJfvs=; b=KVNj8/dhQfhLB5MRDUCu3Z8FEnfxFZ7bSypHfGT5D8AbxhytDRlARtGKutm6AwyR6vCxiW iEoJuQkMI3oHIS4g9kELj0R7W3Qe0spHxhUS6lnODepiP0UmG7scTHBsuRz9r6QQy9ZZ2I 3/0A9E8TH4gx1bk+i6+R3TfFooug0e4= Received: from mail-qk1-f199.google.com (mail-qk1-f199.google.com [209.85.222.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-659-68OA31-TPrWviqwlh86kEg-1; Tue, 21 May 2024 15:36:34 -0400 X-MC-Unique: 68OA31-TPrWviqwlh86kEg-1 Received: by mail-qk1-f199.google.com with SMTP id af79cd13be357-792ba069a97so1775053885a.0 for ; Tue, 21 May 2024 12:36:34 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1716320193; x=1716924993; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Ustz+glglc5DJtPKmYBunhEd8PemFyPnTq9PZEXJfvs=; b=LIz55Kz9/rAJg+OEAjgM6Y7KCrsYvp1va4v7CR/D3LD942IibUJQgBAJ/wsPXaNtmF o01Lti6g7ieJpEwaOj+tfEatUwFZDRYj/QKMqN/IH8u+wZ6cLK8bgAq0q77NxvicHJRt DT7YAZHw45p8gVGZDKULbFWkvM8B+1aBI78Pcqgrn7gyyS7zLgFVVYq7BMa0Aw9Xdf+J xnk9JxNtL/lJjxll+mLDQFJ3qyqt7j6bDecfbqOY2nqs2yxkmBQPpOXgvI+w9k4I3Gcd qOKLK5BCubiYbtVTnIbdE2cAK2HDz6xT0APXFYsrKdiLitCwP8IfEUYWfICy4XVOiNUv NuKg== X-Gm-Message-State: AOJu0YxVsu8kpHokBYqMEXe7rQRzmdwmY4R0ePswMJHyVwGhQG4ZD5Ol lCHCSe66ZfpyjnMoH1418nhwTMig3YIJZECpkQobM2pZxqhXPrtZfWyF4VdkjGxb3jbh3wpY3ak WknTJZjIdO9v+LnN5/dWwR+awznD1urdpsPJUWmeOtXcq98+7MZ/O8S+5ccfWrZWOumiCjHtL9u DarKRhSagxkICmZBfFJqABn18hdrRLiwwIBRao X-Received: by 2002:a05:620a:ec4:b0:792:bb12:95a4 with SMTP id af79cd13be357-792c759adf0mr3302689785a.27.1716320192343; Tue, 21 May 2024 12:36:32 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGwiabhkOp5Yjf0JFap2jQPftkpxFuBujwLg9PcWmD33BSba1Gf7SyRr6SFdZ7JDxqc6+QxRw== X-Received: by 2002:a05:620a:ec4:b0:792:bb12:95a4 with SMTP id af79cd13be357-792c759adf0mr3302687285a.27.1716320191569; Tue, 21 May 2024 12:36:31 -0700 (PDT) Received: from localhost.localdomain (ool-18bb2a2e.dyn.optonline.net. [24.187.42.46]) by smtp.gmail.com with ESMTPSA id af79cd13be357-792bf27f83csm1319439485a.32.2024.05.21.12.36.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 May 2024 12:36:31 -0700 (PDT) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com, Patrick Palka Subject: [PATCH] c++: canonicity of fn types w/ complex eh specs [PR115159] Date: Tue, 21 May 2024 15:36:29 -0400 Message-ID: <20240521193629.4129787-1-ppalka@redhat.com> X-Mailer: git-send-email 2.45.1.216.g4365c6fcf9 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, RCVD_IN_SORBS_WEB, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org 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 Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk? Alternatively, I considered fixing this by incrementing comparing_specializations around the call to comp_except_specs in cp_check_qualified_type, but generally for types whose identity depends on whether comparing_specializations is set we need to use structural equality anyway IIUC. Or maybe it isn't right to fix this outside of modules, and we should instead make modules cope with this cross-function function parameter reference? I briefly tried looking into this but didn't get very far. -- >8 -- Here the member functions QList::g and QList::h are given the same function type since their exception specifications are equivalent according to cp_tree_equal. In doing so however this means that the type of QList::h refers to a function parameter from QList::g, which ends up confusing modules streaming. I'm not sure if modules can be fixed to handle this situation, but regardless it seems weird in principle that a function parameter can escape in such a way. The analogous situation with a trailing return type and decltype auto g(QList &other) -> decltype(f(other)); auto h(QList &other) -> decltype(f(other)); behaves better because we don't canonicalize decltype, and so the function types of g and h are non-canonical and therefore not shared. In light of this, it seems natural to treat function types with complex eh specs as non-canonical as well so that each such function declaration is given a unique function/method type node. The main benefit of type canonicalization is to speed up repeated type comparisons, but it should rare for us to repeatedly compare two otherwise compatible function types with complex exception specifications, so foregoing canonicalization should be harmless IIUC. On the other hand this change simplifies the code responsible for adjusting unparsed eh spec variants. PR c++/115159 gcc/cp/ChangeLog: * tree.cc (build_cp_fntype_variant): Don't reuse a variant with a complex exception specification. Always use structural equality in that case. (fixup_deferred_exception_variants): Always use structural equality for adjusted variants. gcc/testsuite/ChangeLog: * g++.dg/modules/noexcept-2_a.H: New test. * g++.dg/modules/noexcept-2_b.C: New test. --- gcc/cp/tree.cc | 70 +++++++-------------- gcc/testsuite/g++.dg/modules/noexcept-2_a.H | 24 +++++++ gcc/testsuite/g++.dg/modules/noexcept-2_b.C | 4 ++ 3 files changed, 51 insertions(+), 47 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/noexcept-2_a.H create mode 100644 gcc/testsuite/g++.dg/modules/noexcept-2_b.C diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 9d37d255d8d..7987c01520d 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -2761,16 +2761,27 @@ build_cp_fntype_variant (tree type, cp_ref_qualifier rqual, { cp_cv_quals type_quals = TYPE_QUALS (type); - if (cp_check_qualified_type (type, type, type_quals, rqual, raises, late)) - return type; + /* Canonicalize the exception specification. */ + tree cr = flag_noexcept_type ? canonical_eh_spec (raises) : NULL_TREE; + /* For a complex exception specification, always create a distinct + non-canonical variant for simplicity. This also prevents noexcept-specs + that are in terms of a function parameter from getting shared with an + another function. */ + bool complex_p = (cr && cr != noexcept_true_spec + && !UNPARSED_NOEXCEPT_SPEC_P (cr)); + if (!complex_p) + { + if (cp_check_qualified_type (type, type, type_quals, rqual, raises, late)) + return type; - tree v = TYPE_MAIN_VARIANT (type); - for (; v; v = TYPE_NEXT_VARIANT (v)) - if (cp_check_qualified_type (v, type, type_quals, rqual, raises, late)) - return v; + tree v = TYPE_MAIN_VARIANT (type); + for (; v; v = TYPE_NEXT_VARIANT (v)) + if (cp_check_qualified_type (v, type, type_quals, rqual, raises, late)) + return v; + } /* Need to build a new variant. */ - v = build_variant_type_copy (type); + tree v = build_variant_type_copy (type); if (!TYPE_DEPENDENT_P (v)) /* We no longer know that it's not type-dependent. */ TYPE_DEPENDENT_P_VALID (v) = false; @@ -2791,10 +2802,7 @@ build_cp_fntype_variant (tree type, cp_ref_qualifier rqual, break; } - /* Canonicalize the exception specification. */ - tree cr = flag_noexcept_type ? canonical_eh_spec (raises) : NULL_TREE; - - if (TYPE_STRUCTURAL_EQUALITY_P (type)) + if (TYPE_STRUCTURAL_EQUALITY_P (type) || complex_p) /* Propagate structural equality. */ SET_TYPE_STRUCTURAL_EQUALITY (v); else if (TYPE_CANONICAL (type) != type || cr != raises || late) @@ -2812,55 +2820,23 @@ build_cp_fntype_variant (tree type, cp_ref_qualifier rqual, /* TYPE is a function or method type with a deferred exception specification that has been parsed to RAISES. Fixup all the type variants that are affected in place. Via decltype &| noexcept - tricks, the unparsed spec could have escaped into the type system. - The general case is hard to fixup canonical types for. */ + tricks, the unparsed spec could have escaped into the type system. */ void fixup_deferred_exception_variants (tree type, tree raises) { tree original = TYPE_RAISES_EXCEPTIONS (type); - tree cr = flag_noexcept_type ? canonical_eh_spec (raises) : NULL_TREE; gcc_checking_assert (UNPARSED_NOEXCEPT_SPEC_P (original)); - /* Though sucky, this walk will process the canonical variants - first. */ - tree prev = NULL_TREE; for (tree variant = TYPE_MAIN_VARIANT (type); - variant; prev = variant, variant = TYPE_NEXT_VARIANT (variant)) + variant; variant = TYPE_NEXT_VARIANT (variant)) if (TYPE_RAISES_EXCEPTIONS (variant) == original) { gcc_checking_assert (variant != TYPE_MAIN_VARIANT (type)); - if (!TYPE_STRUCTURAL_EQUALITY_P (variant)) - { - cp_cv_quals var_quals = TYPE_QUALS (variant); - cp_ref_qualifier rqual = type_memfn_rqual (variant); - - /* If VARIANT would become a dup (cp_check_qualified_type-wise) - of an existing variant in the variant list of TYPE after its - exception specification has been parsed, elide it. Otherwise, - build_cp_fntype_variant could use it, leading to "canonical - types differ for identical types." */ - tree v = TYPE_MAIN_VARIANT (type); - for (; v; v = TYPE_NEXT_VARIANT (v)) - if (cp_check_qualified_type (v, variant, var_quals, - rqual, cr, false)) - { - /* The main variant will not match V, so PREV will never - be null. */ - TYPE_NEXT_VARIANT (prev) = TYPE_NEXT_VARIANT (variant); - break; - } - TYPE_RAISES_EXCEPTIONS (variant) = raises; - - if (!v) - v = build_cp_fntype_variant (TYPE_CANONICAL (variant), - rqual, cr, false); - TYPE_CANONICAL (variant) = TYPE_CANONICAL (v); - } - else - TYPE_RAISES_EXCEPTIONS (variant) = raises; + SET_TYPE_STRUCTURAL_EQUALITY (variant); + TYPE_RAISES_EXCEPTIONS (variant) = raises; if (!TYPE_DEPENDENT_P (variant)) /* We no longer know that it's not type-dependent. */ diff --git a/gcc/testsuite/g++.dg/modules/noexcept-2_a.H b/gcc/testsuite/g++.dg/modules/noexcept-2_a.H new file mode 100644 index 00000000000..b7144f42d7e --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/noexcept-2_a.H @@ -0,0 +1,24 @@ +// PR c++/115159 +// { dg-additional-options -fmodule-header } +// { dg-module-cmi {} } + +struct QDebug; + +template void f(T); + +template struct QList { + QDebug g(QList &other) noexcept(noexcept(f(other))); + QDebug h(QList &other) noexcept(noexcept(f(other))); +}; + +struct QObjectData { + QList children; +}; + +struct QIODevice { + QObjectData d_ptr; +}; + +struct QDebug { + QDebug(QIODevice); +}; diff --git a/gcc/testsuite/g++.dg/modules/noexcept-2_b.C b/gcc/testsuite/g++.dg/modules/noexcept-2_b.C new file mode 100644 index 00000000000..d34c63add10 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/noexcept-2_b.C @@ -0,0 +1,4 @@ +// PR c++/115159 +// { dg-additional-options "-fmodules-ts -fno-module-lazy" } + +import "noexcept-2_a.H";