From patchwork Wed Nov 22 22:07:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1867514 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=e9nWtbGt; 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 4SbFl02KTvz1yRw for ; Thu, 23 Nov 2023 09:09:00 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 796153948A75 for ; Wed, 22 Nov 2023 22:08:24 +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 90DB03858287 for ; Wed, 22 Nov 2023 22:08:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 90DB03858287 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 90DB03858287 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=1700690892; cv=none; b=xYCweS02yZ2qCefCtbHnOv2dnZgQelT37CRTisCfWpnlPFlgyzAtebMaqDQRI2RxC4yFLTrREBR6PWJj5Q1/yQeFBL9hYxsvU2Gvw5mmX/BRuB4lk5KS2AUkYdKoWS9Cdb6xSRpwL6/qmQmk24wUnh/HNflVgwApM1AWioTW8es= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700690892; c=relaxed/simple; bh=0yJ86xvPYKBltlpPoCk1Ocdj4Nu/1fLKwZUKmj0HumI=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=EDMG0RNhgf22itvxnkKL/Y3qPmUhyYVcoWTcLj6DYK7fi9+yVpgwk8Ceb49aR3fwvJrqxYzu3q+2p57ypBfoUpU9JuI18NS8VlkDeTDEszczN8cRyn/G2fXTAZMhKgx6yccTaMxib5yo7VLsvX5u+0aTYu3Ng36eRbMBxlJ9vCE= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1700690882; 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=jdbWFCuIOjEB2c3VQeB0xsrbeSP0kOvSkGozDg0IReM=; b=e9nWtbGtDjSNlrmtIzxItp6ZBip43TmrOF6GebK7ob0aWeArW/nMq9QHgNHk7WFRvIBsj2 eXWM78qo56DM2ElpbxUr7olcSggA1J8Mji5auAvgoYvJngoIYHdHKnzi386mQ52XFb3e2T tktUS9M/Zvi5wbaxjYjUtm7istjGMG4= Received: from mail-qv1-f72.google.com (mail-qv1-f72.google.com [209.85.219.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-641-rMPoU-h0Owa5iPCjMe4Q1Q-1; Wed, 22 Nov 2023 17:08:01 -0500 X-MC-Unique: rMPoU-h0Owa5iPCjMe4Q1Q-1 Received: by mail-qv1-f72.google.com with SMTP id 6a1803df08f44-679f44810d9so3404616d6.0 for ; Wed, 22 Nov 2023 14:08:00 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700690879; x=1701295679; 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=jdbWFCuIOjEB2c3VQeB0xsrbeSP0kOvSkGozDg0IReM=; b=J7qZScbGMsdLjFwtqhZau334PgDYlo4cE6Bq8fXgsCtfVjl5tiDh1EJxJ5tWaqVGxg qecKdLthL7+DYJiSQ7lAc+Sz6YWU2s4OOmWuZr4ZoW9L4lbQ0pFinWK1vSARTk0SLEGf GQngDeaD0YP8sN2076H1sV1b/mwauRkaQuSvdVLVorTPnANSEkKjUgYKGJ2P8mjWvXbB k/K22aczWn/j2P0Ivwe0a5hA6ZHG+h9ze7Hv2+MlRDp37Au+cbOfLtbYCX1gKONum5YB KSpSsgs/WJrRXjwkTMo7PqC6d3UoCAQhjOVylftpfo6MM47IWni08IVtEnxTW0eEg+/h sjsg== X-Gm-Message-State: AOJu0Yx7q16oRw3eIE5uxexewTNk1UIen6G1Hd9hy/iEscmB/N4ML7aU GuWd5fplFRrMe22+ykfZiYiTEPriMvWQQUlT8RWFAo+PoHRDFfBd7cvSbEl4lPoBNuV0FVYpqqC b7YD7EycsBnGT8JulVy56dc/wMoSBwzMZOZmVHTQ8x+NUQjjmzzFrbZZZBXzhyxna0w+1NbdyqC I= X-Received: by 2002:a05:6214:e8f:b0:671:567d:b13c with SMTP id hf15-20020a0562140e8f00b00671567db13cmr4689535qvb.63.1700690878913; Wed, 22 Nov 2023 14:07:58 -0800 (PST) X-Google-Smtp-Source: AGHT+IEXSZy0R7wB9DNDFubB52tzF1g/3shgRb6piAcJ4YUey5txXJMxq+LlBCQxFBmp6oqfiibOeg== X-Received: by 2002:a05:6214:e8f:b0:671:567d:b13c with SMTP id hf15-20020a0562140e8f00b00671567db13cmr4689489qvb.63.1700690878189; Wed, 22 Nov 2023 14:07:58 -0800 (PST) Received: from localhost.localdomain (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id j4-20020a0c9cc4000000b00679d7e76b64sm130416qvf.126.2023.11.22.14.07.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Nov 2023 14:07:56 -0800 (PST) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com, Patrick Palka Subject: [PATCH] c++: Implement P2582R1, CTAD from inherited constructors Date: Wed, 22 Nov 2023 17:07:31 -0500 Message-ID: <20231122220731.1121607-1-ppalka@redhat.com> X-Mailer: git-send-email 2.43.0.rc1 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.6 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, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE 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? -- >8 -- This patch implements C++23 class template argument deduction from inherited constructors, which is specified in terms of C++20 alias CTAD which we already fully support. The rule for transforming the return type of an inherited guide is specified in terms of a partially specialized class template, but this patch implements it in a simpler way, performing ahead of time deduction instead of instantiation time deduction. I wasn't able to find an example for which this implementation strategy makes a difference, but I didn't look very hard. Support seems good enough to advertise as complete, and there should be no functional change before C++23 mode. There's a couple of FIXMEs, one in inherited_ctad_tweaks for recognizing more forms of inherited constructors, and one in deduction_guides_for for making the cache aware of base-class dependencies. There doesn't seem to be a feature-test macro update for this paper. gcc/cp/ChangeLog: * cp-tree.h (type_targs_deducible_from): Adjust declaration. * pt.cc (alias_ctad_tweaks): Handle C++23 inherited CTAD. (inherited_ctad_tweaks): Define. (type_targs_deducible_from): Add defaulted 'targs_out' parameter. Handle 'tmpl' being a TREE_LIST representing a synthetic alias template. Set 'targs_out' upon success. (ctor_deduction_guides_for): Do inherited_ctad_tweaks for each USING_DECL in C++23 mode. (deduction_guides_for): Add FIXME for stale cache entries in light of inherited CTAD. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/class-deduction67.C: Accept in C++23 mode. * g++.dg/cpp23/class-deduction-inherited1.C: New test. * g++.dg/cpp23/class-deduction-inherited2.C: New test. * g++.dg/cpp23/class-deduction-inherited3.C: New test. --- gcc/cp/cp-tree.h | 2 +- gcc/cp/pt.cc | 176 +++++++++++++++--- .../g++.dg/cpp1z/class-deduction67.C | 5 +- .../g++.dg/cpp23/class-deduction-inherited1.C | 36 ++++ .../g++.dg/cpp23/class-deduction-inherited2.C | 26 +++ .../g++.dg/cpp23/class-deduction-inherited3.C | 16 ++ 6 files changed, 231 insertions(+), 30 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp23/class-deduction-inherited1.C create mode 100644 gcc/testsuite/g++.dg/cpp23/class-deduction-inherited2.C create mode 100644 gcc/testsuite/g++.dg/cpp23/class-deduction-inherited3.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1fa710d7154..633d58b1d12 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7434,7 +7434,7 @@ extern tree fn_type_unification (tree, tree, tree, bool, bool); extern void mark_decl_instantiated (tree, int); extern int more_specialized_fn (tree, tree, int); -extern bool type_targs_deducible_from (tree, tree); +extern bool type_targs_deducible_from (tree, tree, tree * = nullptr); extern void do_decl_instantiation (tree, tree); extern void do_type_instantiation (tree, tree, tsubst_flags_t); extern bool always_instantiate_p (tree); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 324f6f01555..75f5bc9bed5 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -223,6 +223,9 @@ static void instantiate_body (tree pattern, tree args, tree d, bool nested); static tree maybe_dependent_member_ref (tree, tree, tsubst_flags_t, tree); static void mark_template_arguments_used (tree, tree); static bool uses_outer_template_parms (tree); +static tree alias_ctad_tweaks (tree, tree); +static tree inherited_ctad_tweaks (tree, tree, tsubst_flags_t); +static tree deduction_guides_for (tree, bool&, tsubst_flags_t); /* Make the current scope suitable for access checking when we are processing T. T can be FUNCTION_DECL for instantiated function @@ -29753,8 +29756,6 @@ is_spec_or_derived (tree etype, tree tmpl) return !err; } -static tree alias_ctad_tweaks (tree, tree); - /* Return a C++20 aggregate deduction candidate for TYPE initialized from INIT. */ @@ -29859,7 +29860,13 @@ maybe_aggr_guide (tree tmpl, tree init, vec *args) } /* UGUIDES are the deduction guides for the underlying template of alias - template TMPL; adjust them to be deduction guides for TMPL. */ + template TMPL; adjust them to be deduction guides for TMPL. + + This routine also handles C++23 inherited CTAD, in which case TMPL is a + TREE_LIST representing a synthetic alias template whose TREE_PURPOSE is + the template parameter list of the alias template (equivalently, of the + derived class) and TREE_VALUE the defining-type-id (equivalently, the + base whose guides we're inheriting). UGUIDES are the base's guides. */ static tree alias_ctad_tweaks (tree tmpl, tree uguides) @@ -29903,13 +29910,30 @@ alias_ctad_tweaks (tree tmpl, tree uguides) * The explicit-specifier of f' is the explicit-specifier of g (if any). */ + enum { alias, inherited } ctad_kind; + + tree atype; + tree fullatparms; + tree utype; + if (TREE_CODE (tmpl) == TEMPLATE_DECL) + { + ctad_kind = alias; + atype = TREE_TYPE (tmpl); + fullatparms = DECL_TEMPLATE_PARMS (tmpl); + utype = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl)); + } + else + { + ctad_kind = inherited; + atype = NULL_TREE; + fullatparms = TREE_PURPOSE (tmpl); + utype = TREE_VALUE (tmpl); + } + tsubst_flags_t complain = tf_warning_or_error; - tree atype = TREE_TYPE (tmpl); tree aguides = NULL_TREE; - tree fullatparms = DECL_TEMPLATE_PARMS (tmpl); tree atparms = INNERMOST_TEMPLATE_PARMS (fullatparms); unsigned natparms = TREE_VEC_LENGTH (atparms); - tree utype = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl)); for (ovl_iterator iter (uguides); iter; ++iter) { tree f = *iter; @@ -29947,7 +29971,7 @@ alias_ctad_tweaks (tree tmpl, tree uguides) /* Set current_template_parms as in build_deduction_guide. */ auto ctp = make_temp_override (current_template_parms); - current_template_parms = copy_node (DECL_TEMPLATE_PARMS (tmpl)); + current_template_parms = copy_node (fullatparms); TREE_VALUE (current_template_parms) = gtparms; j = 0; @@ -30023,9 +30047,10 @@ alias_ctad_tweaks (tree tmpl, tree uguides) /* Add a constraint that the return type matches the instantiation of A with the same template arguments. */ ret = TREE_TYPE (TREE_TYPE (fprime)); - if (!same_type_p (atype, ret) - /* FIXME this should mean they don't compare as equivalent. */ - || dependent_alias_template_spec_p (atype, nt_opaque)) + if (ctad_kind == alias + && (!same_type_p (atype, ret) + /* FIXME this should mean they don't compare as equivalent. */ + || dependent_alias_template_spec_p (atype, nt_opaque))) { tree same = finish_trait_expr (loc, CPTK_IS_DEDUCIBLE, tmpl, ret); ci = append_constraint (ci, same); @@ -30042,8 +30067,37 @@ alias_ctad_tweaks (tree tmpl, tree uguides) /* For a non-template deduction guide, if the arguments of A aren't deducible from the return type, don't add the candidate. */ non_template: - if (!type_targs_deducible_from (tmpl, ret)) + if (ctad_kind == alias + && !type_targs_deducible_from (tmpl, ret)) + continue; + } + + /* Rewrite the return type of the inherited guide in terms of the + derived class. This is specified as replacing the return type R + with typename CC::type where the partially specialized CC maps a + base class specialization to a specialization of the derived class + having such a base (inducing substitution failure if no such derived + class exists). + + As specified this mapping would be done at instantiation time using + non-dependent template arguments, but we do it ahead of time using + the generic arguments. This seems to be good enough since generic + deduction should succeed only if concrete deduction would. */ + if (ctad_kind == inherited) + { + tree targs; + if (!type_targs_deducible_from (tmpl, ret, &targs)) continue; + + if (TREE_CODE (f) != TEMPLATE_DECL) + fprime = copy_decl (fprime); + tree fntype = TREE_TYPE (fprime); + ret = lookup_template_class (TPARMS_PRIMARY_TEMPLATE (atparms), targs, + in_decl, NULL_TREE, false, complain); + fntype = build_function_type (ret, TYPE_ARG_TYPES (fntype)); + TREE_TYPE (fprime) = fntype; + if (TREE_CODE (fprime) == TEMPLATE_DECL) + TREE_TYPE (DECL_TEMPLATE_RESULT (fprime)) = fntype; } aguides = lookup_add (fprime, aguides); @@ -30052,6 +30106,45 @@ alias_ctad_tweaks (tree tmpl, tree uguides) return aguides; } +/* CTOR is a using-declaration inheriting the constructors of some base of the + class template TMPL; adjust the base's guides be deduction guides for TMPL. */ + +static tree +inherited_ctad_tweaks (tree tmpl, tree ctor, tsubst_flags_t complain) +{ + /* [over.match.class.deduct]: In addition, if C is defined and inherits + constructors ([namespace.udecl]) from a direct base class denoted in the + base-specifier-list by a class-or-decltype B, let A be an alias template + whose template parameter list is that of C and whose defining-type-id is + B. If A is a deducible template ([dcl.type.simple]), the set contains the + guides of A with the return type R of each guide replaced with typename + CC::type given a class template + + template class CC; + + whose primary template is not defined and with a single partial + specialization whose template parameter list is that of A and whose + template argument list is a specialization of A with the template argument + list of A ([temp.dep.type]) having a member typedef type designating a + template specialization with the template argument list of A but with C as + the template. */ + + /* FIXME: Also recognize inherited constructors of the form 'using C::B::B', + which seem to be represented with TYPENAME_TYPE C::B as USING_DECL_SCOPE? + And recognize constructors inherited from a non-dependent base class, which + seem to be missing from the overload set entirely? */ + tree scope = USING_DECL_SCOPE (ctor); + if (!CLASS_TYPE_P (scope) + || !CLASSTYPE_TEMPLATE_INFO (scope)) + return NULL_TREE; + + tree t = build_tree_list (DECL_TEMPLATE_PARMS (tmpl), scope); + bool any_dguides_p; + tree uguides = deduction_guides_for (TYPE_TI_TEMPLATE (scope), + any_dguides_p, complain); + return alias_ctad_tweaks (t, uguides); +} + /* True iff template arguments for TMPL can be deduced from TYPE. Used to implement CPTK_IS_DEDUCIBLE for alias CTAD according to [over.match.class.deduct]. @@ -30060,23 +30153,37 @@ alias_ctad_tweaks (tree tmpl, tree uguides) should be parallel to that of get_partial_spec_bindings. */ bool -type_targs_deducible_from (tree tmpl, tree type) +type_targs_deducible_from (tree tmpl, tree type, tree *targs_out /* = nullptr */) { - tree tparms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl); + tree tparms, ttype; + if (TREE_CODE (tmpl) == TEMPLATE_DECL) + { + /* If tmpl is a class template, this is trivial: it's deducible if TYPE is a + specialization of TMPL. */ + if (DECL_CLASS_TEMPLATE_P (tmpl)) + return (CLASS_TYPE_P (type) + && CLASSTYPE_TEMPLATE_INFO (type) + && CLASSTYPE_TI_TEMPLATE (type) == tmpl); + + /* Otherwise it's an alias template. */ + tparms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl); + ttype = TREE_TYPE (tmpl); + } + else + { + /* TMPL is a synthetic alias template represented as a TREE_LIST as + per alias_ctad_tweaks. */ + tparms = INNERMOST_TEMPLATE_PARMS (TREE_PURPOSE (tmpl)); + ttype = TREE_VALUE (tmpl); + tmpl = TI_TEMPLATE (TYPE_TEMPLATE_INFO_MAYBE_ALIAS (ttype)); + } + int len = TREE_VEC_LENGTH (tparms); tree targs = make_tree_vec (len); bool tried_array_deduction = (cxx_dialect < cxx17); - /* If tmpl is a class template, this is trivial: it's deducible if TYPE is a - specialization of TMPL. */ - if (DECL_CLASS_TEMPLATE_P (tmpl)) - return (CLASS_TYPE_P (type) - && CLASSTYPE_TEMPLATE_INFO (type) - && CLASSTYPE_TI_TEMPLATE (type) == tmpl); - - /* Otherwise it's an alias template. */ again: - if (unify (tparms, targs, TREE_TYPE (tmpl), type, + if (unify (tparms, targs, ttype, type, UNIFY_ALLOW_NONE, false)) return false; @@ -30091,7 +30198,7 @@ type_targs_deducible_from (tree tmpl, tree type) if (!tried_array_deduction && TREE_CODE (tparm) == TYPE_DECL) { - try_array_deduction (tparms, targs, TREE_TYPE (tmpl)); + try_array_deduction (tparms, targs, ttype); tried_array_deduction = true; if (TREE_VEC_ELT (targs, i)) goto again; @@ -30125,7 +30232,12 @@ type_targs_deducible_from (tree tmpl, tree type) /* I believe we don't need the template_template_parm_bindings_ok_p call because coerce_template_parms did coerce_template_template_parms. */ - return constraints_satisfied_p (tmpl, targs); + if (!constraints_satisfied_p (tmpl, targs)) + return false; + + if (targs_out) + *targs_out = targs; + return true; } /* Return artificial deduction guides built from the constructors of class @@ -30141,7 +30253,7 @@ ctor_deduction_guides_for (tree tmpl, tsubst_flags_t complain) for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (type)); iter; ++iter) { - /* Skip inherited constructors. */ + /* We handle C++23 inherited CTAD below. */ if (iter.using_p ()) continue; @@ -30149,6 +30261,15 @@ ctor_deduction_guides_for (tree tmpl, tsubst_flags_t complain) cands = lookup_add (guide, cands); } + if (cxx_dialect >= cxx23) + for (tree ctor : ovl_range (CLASSTYPE_CONSTRUCTORS (type))) + if (TREE_CODE (ctor) == USING_DECL) + { + tree uguides = inherited_ctad_tweaks (tmpl, ctor, complain); + if (uguides) + cands = lookup_add (uguides, cands); + } + /* Add implicit default constructor deduction guide. */ if (!TYPE_HAS_USER_CONSTRUCTOR (type)) { @@ -30198,7 +30319,10 @@ deduction_guides_for (tree tmpl, bool &any_dguides_p, tsubst_flags_t complain) } /* Cache the deduction guides for a template. We also remember the result of - lookup, and rebuild everything if it changes; should be very rare. */ + lookup, and rebuild everything if it changes; should be very rare. + + FIXME: Also rebuild if this is a class template that inherits guides from a + base class, and lookup for the latter changed. */ tree_pair_p cache = NULL; if (tree_pair_p &r = hash_map_safe_get_or_insert (dguide_cache, tmpl)) diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction67.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction67.C index 4624794c4b7..74f92325d7a 100644 --- a/gcc/testsuite/g++.dg/cpp1z/class-deduction67.C +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction67.C @@ -1,5 +1,4 @@ -// Deduction from inherited constructors isn't supported yet, but we shouldn't -// crash. It may well be supported in C++23. +// Deduction from inherited constructors isn't supported before C++23. //{ dg-do compile { target c++17 } } @@ -17,5 +16,5 @@ int main() { B b = 42; // { dg-line init } // { dg-prune-output "no matching function" } - // { dg-error "class template argument deduction" "" { target *-*-* } init } + // { dg-error "class template argument deduction" "" { target c++23_down } init } } diff --git a/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited1.C b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited1.C new file mode 100644 index 00000000000..aa1948531e1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited1.C @@ -0,0 +1,36 @@ +// Modified example from P2582R1 +// { dg-do compile { target c++23 } } + +template struct B { + B(T); +}; +B(bool) -> B; +template struct C : public B { + using B::B; +}; +template struct D : public B {}; + +C c(42); // OK, deduces C +using ty1 = decltype(C(42)); +using ty1 = C; + +D d(42); // { dg-error "deduction|no match" } + +C c2(true); // OK, deduces C +using ty2 = decltype(C(true)); +using ty2 = C; + +template struct E : public B { + using B::B; +}; + +E e(42); // { dg-error "deduction|no match" } + +template struct F { + F(T, U, V); +}; +template struct G : F { + using F::F; +}; + +G g(true, 'a', 1); // OK, deduces G diff --git a/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited2.C b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited2.C new file mode 100644 index 00000000000..cb3c595f316 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited2.C @@ -0,0 +1,26 @@ +// { dg-do compile { target c++23 } } + +template struct F { + F(T, U, V); // #1 + F(T*, U*, V*); // #2 + template + F(int, int, W); // #3 +}; + +F(bool, bool, bool) -> F; + +template struct G : F { + using F::F; +}; + +using ty1 = decltype(G(true, 'a', 1)); // uses #1 +using ty1 = G; + +using ty2 = decltype(G((bool*)0, (char*)0, (int*)0)); // uses #2 +using ty2 = G; + +using ty3 = decltype(G(0, 0, 0)); // uses #3 +using ty3 = G; + +using ty4 = decltype(G(true, true, true)); // uses #4 +using ty4 = G; diff --git a/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited3.C b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited3.C new file mode 100644 index 00000000000..57e323b5124 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited3.C @@ -0,0 +1,16 @@ +// { dg-do compile { target c++23 } } + +template +struct A { + A(T); + template A(T, U); +}; + +template +struct B : A { + using A::A; +}; + +using type = decltype(B(0)); +using type = decltype(B(0, 0)); +using type = B;