From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 ABC1A3858CD1 for ; Fri, 24 Nov 2023 18:18:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org ABC1A3858CD1 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 ABC1A3858CD1 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=1700849895; cv=none; b=Hu5ZPjz0NmgAiODsMVG3cBsqmwBGQy4MZSJhOa0SzdK6shfML6ZgOtYDfXRm+gVQjoYoK8Zbfo1GR0FrOOdZ2O0pyj8ar4o4h4deza5ty1W2gVXGuFzrnDxp2YcBzhl8woVYv2AEwKi6igE6NQzV5Dc8TnlvNVyEj6UDMX/rUAE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700849895; c=relaxed/simple; bh=F9FJgzXAqXO30DuQKaiiS7qd8Inhoi/MH4VwohlTG+4=; h=DKIM-Signature:From:Date:To:Subject:Message-ID:MIME-Version; b=E1sFvxXaHbWlLPUbHh49VGDj01/hicv7J08Or6BlPywKOC0gY7gxMoXphCaPreZdbkIoK+iaR2phKVxJhE/CO3fzmkyCbFWavDEMdIqimEKRWuzaraX4mNTOpdIg9by2xcy/i5RyOiXsnE8xDKGK/PYqBV2PiJGgx75qd4T8XCg= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1700849892; 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: in-reply-to:in-reply-to:references:references; bh=YICDajTSLcuggAv8vRRIJuoqDXYO/UA9XUvL0w80+90=; b=BB/QqhL9T8rFFLF5dGAnZE0zAUf9Xm6pJTzNoFEbebaT2/0BoLX5XWsPZayzatFgkHH1yN cmYJ+qbQdrAlU7EfQh/0/N8Xa0zkAXhGx5ELgSMlG5lk2Gk3ffZx+pRsGyWJeSUqxm95W/ sNKokj0SBUPZI3y2UOYBsdcVRqUvez0= Received: from mail-qt1-f197.google.com (mail-qt1-f197.google.com [209.85.160.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-561-Tj5X9BYwMpGFfP_wbbxyXQ-1; Fri, 24 Nov 2023 13:18:10 -0500 X-MC-Unique: Tj5X9BYwMpGFfP_wbbxyXQ-1 Received: by mail-qt1-f197.google.com with SMTP id d75a77b69052e-41cb7c104ddso25625201cf.0 for ; Fri, 24 Nov 2023 10:18:10 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700849890; x=1701454690; h=mime-version:references:message-id:in-reply-to:subject:cc:to:date :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=YICDajTSLcuggAv8vRRIJuoqDXYO/UA9XUvL0w80+90=; b=ZXoy4A0tzyQuepB9AjoioD5LkDvob7gtA7VNCY87kbbHBEzpYE1tZ3S3PbqHmeWmcp rSxL6E1XSmt3d9blm8iTPXjG32kkW9sdm3gy3pjYxhmtMtksBiOhMp6hzucp0a9qB4s2 Xdm4qSMa9Do4Gmr7nulMGg0juNhJ969QI6lKEJQamE9K++K9vK3VwizkR+qkOHjjz9bN QelsVV4Xve0lsCssd6Ba7lRxHTuDoIwC/GkzxbWScTpP6I5fsNwfKn/trgCe//tOR3vy IqsYMVayziYz6s+MKszDD9NazolSSq2EzxDarMw5cSNZrzBk2M74ewZQwO2C7DZdNmIn QLHQ== X-Gm-Message-State: AOJu0YxaMAybgmqKLz62WHvdUTNWTyoHatLKhemqO2s48MyWfas9B++S u4X8FJj2saqpsRGghiIuxdwfJxEbvCVtsmF4pBnKejqgm1ocItF6U+pblFPq/huH5zHOuWWDrlu aISZ1wdovbWEVlpE9Ag== X-Received: by 2002:a05:622a:40b:b0:41e:2314:8dde with SMTP id n11-20020a05622a040b00b0041e23148ddemr3956794qtx.38.1700849890067; Fri, 24 Nov 2023 10:18:10 -0800 (PST) X-Google-Smtp-Source: AGHT+IEMkSp9uX/ZybnCMePHoRDuTbk0zHu7r51hBnYbNvwHSUGhwfXN3XyKLGkYAldV5a0V6N/PXA== X-Received: by 2002:a05:622a:40b:b0:41e:2314:8dde with SMTP id n11-20020a05622a040b00b0041e23148ddemr3956761qtx.38.1700849889492; Fri, 24 Nov 2023 10:18:09 -0800 (PST) Received: from [192.168.1.130] (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id bb15-20020a05622a1b0f00b0041aff9339a2sm282365qtb.22.2023.11.24.10.18.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Nov 2023 10:18:09 -0800 (PST) From: Patrick Palka X-Google-Original-From: Patrick Palka Date: Fri, 24 Nov 2023 13:18:08 -0500 (EST) To: Patrick Palka cc: gcc-patches@gcc.gnu.org, jason@redhat.com Subject: Re: [PATCH] c++: Implement P2582R1, CTAD from inherited constructors In-Reply-To: <20231122220731.1121607-1-ppalka@redhat.com> Message-ID: References: <20231122220731.1121607-1-ppalka@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-13.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,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 List-Id: On Wed, 22 Nov 2023, Patrick Palka wrote: > 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. > Here's v2 with some minor changes: * set processing_template_decl when rewriting the return type of a template guide * rather than adding an out parameter to type_targs_deducible_from, just make it return NULL_TREE or the deduced args * add a testcase demonstrating each of the FIXMEs -- >8 -- gcc/cp/ChangeLog: * cp-tree.h (type_targs_deducible_from): Adjust return type. * pt.cc (alias_ctad_tweaks): Handle C++23 inherited CTAD. (inherited_ctad_tweaks): Define. (type_targs_deducible_from): Return the deduced arguments or NULL_TREE instead of a bool. Handle 'tmpl' being a TREE_LIST representing a synthetic alias template. (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. * g++.dg/cpp23/class-deduction-inherited4.C: New test. --- gcc/cp/cp-tree.h | 2 +- gcc/cp/pt.cc | 186 +++++++++++++++--- .../g++.dg/cpp1z/class-deduction67.C | 5 +- .../g++.dg/cpp23/class-deduction-inherited1.C | 38 ++++ .../g++.dg/cpp23/class-deduction-inherited2.C | 26 +++ .../g++.dg/cpp23/class-deduction-inherited3.C | 16 ++ .../g++.dg/cpp23/class-deduction-inherited4.C | 32 +++ 7 files changed, 272 insertions(+), 33 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 create mode 100644 gcc/testsuite/g++.dg/cpp23/class-deduction-inherited4.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7b0b7c6a17e..abc467fb290 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7457,7 +7457,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 tree type_targs_deducible_from (tree, tree); 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 092e6fdfd36..8b7aa96cf01 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 @@ -29736,8 +29739,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. */ @@ -29842,7 +29843,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) @@ -29886,13 +29893,27 @@ 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, fullatparms, 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; @@ -29930,7 +29951,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; @@ -30006,9 +30027,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); @@ -30025,43 +30047,134 @@ 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) + { + processing_template_decl_sentinel ptds (/*reset*/false); + if (TREE_CODE (fprime) == TEMPLATE_DECL) + ++processing_template_decl; + + if (TREE_CODE (f) != TEMPLATE_DECL) + fprime = copy_decl (fprime); + else + /* Our fprime is already a copy. */; + + 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); } return aguides; } -/* True iff template arguments for TMPL can be deduced from TYPE. +/* 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); +} + +/* If template arguments for TMPL can be deduced from TYPE, return + the deduced arguments, otherwise return NULL_TREE. Used to implement CPTK_IS_DEDUCIBLE for alias CTAD according to [over.match.class.deduct]. This check is specified in terms of partial specialization, so the behavior should be parallel to that of get_partial_spec_bindings. */ -bool +tree type_targs_deducible_from (tree tmpl, tree type) { - 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)) + { + if (CLASS_TYPE_P (type) + && CLASSTYPE_TEMPLATE_INFO (type) + && CLASSTYPE_TI_TEMPLATE (type) == tmpl) + return INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)); + else + return NULL_TREE; + } + + /* 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; + return NULL_TREE; /* We don't fail on an undeduced targ the second time through (like get_partial_spec_bindings) because we're going to try defaults. */ @@ -30074,7 +30187,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; @@ -30103,12 +30216,15 @@ type_targs_deducible_from (tree tmpl, tree type) partial specialization can't have default targs. */ targs = coerce_template_parms (tparms, targs, tmpl, tf_none); if (targs == error_mark_node) - return false; + return NULL_TREE; /* 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 NULL_TREE; + + return targs; } /* Return artificial deduction guides built from the constructors of class @@ -30124,7 +30240,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; @@ -30132,6 +30248,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)) { @@ -30181,7 +30306,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..5fd1270e819 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited1.C @@ -0,0 +1,38 @@ +// 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); +using ty1 = C; + +D d(42); // { dg-error "deduction|no match" } + +C c2(true); // OK, deduces C +using ty2 = decltype(c2); +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 +using ty3 = decltype(g); +using ty3 = 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; diff --git a/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited4.C b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited4.C new file mode 100644 index 00000000000..f706ebe9bb7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited4.C @@ -0,0 +1,32 @@ +// { dg-do compile { target c++23 } } + +template +struct A { A(T); }; + +template +struct B : A { + using B::A::A; // FIXME: we don't notice this inherited ctor during CTAD +}; + +using ty1 = decltype(B(0)); // { dg-bogus "" "" { xfail *-*-* } } +using ty1 = B; + +template +struct C : A { + using A::A; // FIXME: we don't notice this one either +}; + +using ty2 = decltype(C(0)); // { dg-bogus "" "" { xfail *-*-* } } +using ty2 = C; + +template +struct D : A { + using A::A; +}; + +using ty3 = decltype(D(0)); +using ty3 = D; + +A(int) -> A; // FIXME: we need to rebuild the guides of D +using ty4 = decltype(D(0)); +using ty4 = D; // { dg-bogus "conflicting" "" { xfail *-*-* } } -- 2.43.0.rc1