From patchwork Sat Feb 18 21:42:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 59026 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp562826wrn; Sat, 18 Feb 2023 13:44:08 -0800 (PST) X-Google-Smtp-Source: AK7set+uFf3K47s1h27jnAgxZC0vS6tfjL3R7coGqrD53IhC/8S1Z3dgIUUXkYrBBqkUiYddRIO0 X-Received: by 2002:aa7:d307:0:b0:4ae:eab6:9fac with SMTP id p7-20020aa7d307000000b004aeeab69facmr473368edq.32.1676756648004; Sat, 18 Feb 2023 13:44:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1676756647; cv=none; d=google.com; s=arc-20160816; b=Lpu0+USvyzjmbc8sg3DFnbzu3+imddieiMBotKo2XhWd2sNdkQ16QKhl3qu6g82Rgn lJKWvWZ1YtwwsqVWmWm9oa++gy7ItKkbtroNBXoJ+U9vmQAXkPHdY0kWsA0nGKSMvVyF h/iogvHBtXDSjlnzYaSlJWcQKZnGhgTgdq4iD/PkXRibWjG65Ilft6EzWdD1r6kl1LSW UCV0rx0Z1ehIsQp18z3aphDiUqmjxFrLN4AFltR/BZFwqHxOzEpQfCn9y4hK3CYYeg8/ GtNa9MhWFbOS0i8bavD4pxpiLTyPboFzq4bp/JJkrWCQucNQ+ensTwbnAj7NZ2LnB95J Yz7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:message-id:date:subject:to :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=bGjw5OHQRqdFgeSrZbqQOMv+Iw7yRa54NAnMWcRLu5I=; b=pwtwccib6gijPY9GKj/jCRw/o+GeEbOgVkkhFqHSvHTh6IhqjnA38uesy4v3p76Mc/ 0P0xrAYavQieSO1wcTkYY0NmUqouu6bP4aVQGERQ3aZcwOEdLouNknJJPAcIFSc2mkS7 k0V3GAtrqMrE2zmXJmTVpWcHFtD0PrfB6Z0o5eOB08h5RZjeW/za5nHMaDWz8K3Zgakb dgFF+NPrk6f/Dgeq5tK3sRMmcSUsWyk96f+2qheCZ8/MBT0AgcM/FQw+FfvQkQxFvwFM vn7XbN8AHXWuLR8/6+1QAVPIG6wIrLU7wPlftfY39HBQXeI1NMbJelvQM1m+ODutB0pg DPnA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b="UFPgrC/3"; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id w12-20020aa7cb4c000000b004acc42357cfsi9811432edt.364.2023.02.18.13.44.07 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Feb 2023 13:44:07 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b="UFPgrC/3"; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3C3EA3854806 for ; Sat, 18 Feb 2023 21:43:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3C3EA3854806 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1676756612; bh=bGjw5OHQRqdFgeSrZbqQOMv+Iw7yRa54NAnMWcRLu5I=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=UFPgrC/3B9XIwtqfydu2GseJHU6Dsg7QLmfYDVa6KZUTR87sNJOOoBas/Jokx8BL7 H2GdHGP/ErVt4AUmc83jQ+dLzvR9nmMdVXxe1IfHKZVWTGfLLpp4+0LqIFH/HT+5PY Bjm8CLplWj3MVjyiKmE+98f+wsYxcRR7gsr6rkkQ= 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 ESMTPS id C043F3858D32 for ; Sat, 18 Feb 2023 21:42:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C043F3858D32 Received: from mail-qv1-f70.google.com (mail-qv1-f70.google.com [209.85.219.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-534-QgFDl4FMObSoCcRUKUDX4w-1; Sat, 18 Feb 2023 16:42:44 -0500 X-MC-Unique: QgFDl4FMObSoCcRUKUDX4w-1 Received: by mail-qv1-f70.google.com with SMTP id mv6-20020a056214338600b00570ccb820abso1021602qvb.5 for ; Sat, 18 Feb 2023 13:42:44 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=bGjw5OHQRqdFgeSrZbqQOMv+Iw7yRa54NAnMWcRLu5I=; b=vrElGEctbFwmIgT/D2HRu4zOrpdgtyXTpbk1dDa95jMIim4HtZApI2zoLYTbgbyTUS BvdBUG9zZiA5ZZXjQKgMT+R/H+SGI7geVuzhJ8HVsRJkXgBs5xxwM15wOnFx2J3W0oob kGFvL5oagawfirccSXnmsJqjR+JC+PWQw5qa7tBRdggfZMi//3YinHrCwdOGzDauoWri YJp+4gFwci8edCgULQlq1jpoYOswoJvuaAS8PbcmfURqRL4U7p9SQcXhwUHl5y4dVs3a sruDZz3SiYBr8UyuwYvEfQ9xcnWX2nzn7ySvjG7hC6nmQTv4bdczKQqD89kH29EjSqhP VXKw== X-Gm-Message-State: AO0yUKVDIyNn+oE1V7xNRBuLyH13C7zszGzUpLspBspxGz4/BhN7rKaY 0nFpcelVCx9ChjyHpms/+iBl5q9Uxv+IqPDRUpNp+r/8S1Onozp1LUdL/UmBMmCdBZiW6ZRqo3g 9Kis2GImAXjQDvhvMMnhO+fAUZZyOEciGm77y72M05CXf5Ljz06YSFqJ0doW3hVpzRCY6ip4= X-Received: by 2002:ad4:5963:0:b0:56c:1574:6538 with SMTP id eq3-20020ad45963000000b0056c15746538mr464492qvb.42.1676756563179; Sat, 18 Feb 2023 13:42:43 -0800 (PST) X-Received: by 2002:ad4:5963:0:b0:56c:1574:6538 with SMTP id eq3-20020ad45963000000b0056c15746538mr464454qvb.42.1676756562522; Sat, 18 Feb 2023 13:42:42 -0800 (PST) Received: from jason.com (130-44-159-43.s15913.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.159.43]) by smtp.gmail.com with ESMTPSA id u62-20020a372e41000000b0073d85e77fa9sm263717qkh.74.2023.02.18.13.42.41 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Feb 2023 13:42:41 -0800 (PST) To: gcc-patches@gcc.gnu.org Subject: [PATCH RFC 1/3] c++: add __is_deducible trait [PR105841] Date: Sat, 18 Feb 2023 16:42:37 -0500 Message-Id: <20230218214239.2297623-1-jason@redhat.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.5 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_H2, 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jason Merrill via Gcc-patches From: Jason Merrill Reply-To: Jason Merrill Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1758206779226647361?= X-GMAIL-MSGID: =?utf-8?q?1758206779226647361?= Tested x86_64-pc-linux-gnu. Since this is fixing experimental (C++20) functionality, I think it's reasonable to apply now; I'm interested in other opinions, and thoughts about the user-facing functionality. I'm thinking to make it internal-only for GCC 13 at least by adding a space in the name, but does this look useful to the library? -- 8< -- C++20 class template argument deduction for an alias template involves adding a constraint that the template arguments for the alias template can be deduced from the return type of the deduction guide for the underlying class template. In the standard, this is modeled as defining a class template with a partial specialization, but it's much more efficient to implement with a trait that directly tries to perform the deduction. The first argument to the trait is a template rather than a type, so various places needed to be adjusted to accommodate that. PR c++/105841 gcc/ChangeLog: * doc/extend.texi (Type Traits):: Document __is_deducible. gcc/cp/ChangeLog: * cp-trait.def (IS_DEDUCIBLE): New. * cxx-pretty-print.cc (pp_cxx_trait): Handle non-type. * parser.cc (cp_parser_trait): Likewise. * pt.cc (tsubst_copy_and_build): Likewise. (type_targs_deducible_from): New. (alias_ctad_tweaks): Use it. * semantics.cc (trait_expr_value): Handle CPTK_IS_DEDUCIBLE. (finish_trait_expr): Likewise. * constraint.cc (diagnose_trait_expr): Likewise. * cp-tree.h (type_targs_deducible_from): Declare. gcc/testsuite/ChangeLog: * g++.dg/ext/is_deducible1.C: New test. --- gcc/doc/extend.texi | 4 +++ gcc/cp/cp-tree.h | 1 + gcc/cp/constraint.cc | 3 ++ gcc/cp/cxx-pretty-print.cc | 5 +++- gcc/cp/parser.cc | 20 +++++++++++--- gcc/cp/pt.cc | 35 +++++++++++++++++------- gcc/cp/semantics.cc | 11 ++++++++ gcc/testsuite/g++.dg/ext/is_deducible1.C | 27 ++++++++++++++++++ gcc/cp/cp-trait.def | 1 + 9 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/is_deducible1.C base-commit: 9944ca17c0766623bce260684edc614def7ea761 diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 1ae68b0f20a..898701424ad 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -25207,6 +25207,10 @@ type. A diagnostic is produced if this requirement is not met. If @code{type} is a cv-qualified class type, and not a union type ([basic.compound]) the trait is @code{true}, else it is @code{false}. +@item __is_deducible (template, type) +If template arguments for @code{template} can be deduced from +@code{type} or obtained from default template arguments. + @item __is_empty (type) If @code{__is_class (type)} is @code{false} then the trait is @code{false}. Otherwise @code{type} is considered empty if and only if: @code{type} diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5595335bbf7..e79150ca4d8 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7372,6 +7372,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 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/constraint.cc b/gcc/cp/constraint.cc index 9374327008b..a28c85178fe 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -3797,6 +3797,9 @@ diagnose_trait_expr (tree expr, tree args) inform (loc, " %qT is not a reference that binds to a temporary " "object of type %qT (copy-initialization)", t1, t2); break; + case CPTK_IS_DEDUCIBLE: + inform (loc, " %qD is not deducible from %qT", t1, t2); + break; #define DEFTRAIT_TYPE(CODE, NAME, ARITY) \ case CPTK_##CODE: #include "cp-trait.def" diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc index bea52a608f1..4ebd957decd 100644 --- a/gcc/cp/cxx-pretty-print.cc +++ b/gcc/cp/cxx-pretty-print.cc @@ -2626,7 +2626,10 @@ pp_cxx_trait (cxx_pretty_printer *pp, tree t) } pp_cxx_left_paren (pp); - pp->type_id (type1); + if (DECL_P (type1)) + pp->expression (type1); + else + pp->type_id (type1); if (type2) { if (TREE_CODE (type2) != TREE_LIST) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 1a124f5395e..68950cace78 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -10960,10 +10960,22 @@ cp_parser_trait (cp_parser* parser, enum rid keyword) matching_parens parens; parens.require_open (parser); - { - type_id_in_expr_sentinel s (parser); - type1 = cp_parser_type_id (parser); - } + if (kind == CPTK_IS_DEDUCIBLE) + { + const cp_token* token = cp_lexer_peek_token (parser->lexer); + type1 = cp_parser_id_expression (parser, + /*template_keyword_p=*/false, + /*check_dependency_p=*/true, + nullptr, + /*declarator_p=*/false, + /*optional_p=*/false); + type1 = cp_parser_lookup_name_simple (parser, type1, token->location); + } + else + { + type_id_in_expr_sentinel s (parser); + type1 = cp_parser_type_id (parser); + } if (type1 == error_mark_node) return error_mark_node; diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index b1ac7d4beb4..2aa06557b99 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -21577,8 +21577,9 @@ tsubst_copy_and_build (tree t, case TRAIT_EXPR: { - tree type1 = tsubst (TRAIT_EXPR_TYPE1 (t), args, - complain, in_decl); + tree type1 = TRAIT_EXPR_TYPE1 (t); + if (TREE_CODE (type1) != TEMPLATE_DECL) + type1 = tsubst (type1, args, complain, in_decl); tree type2 = tsubst (TRAIT_EXPR_TYPE2 (t), args, complain, in_decl); RETURN (finish_trait_expr (TRAIT_EXPR_LOCATION (t), @@ -29979,7 +29980,7 @@ alias_ctad_tweaks (tree tmpl, tree uguides) /* This implementation differs from the above in two significant ways: 1) We include all template parameters of A, not just some. - 2) The added constraint is same_type instead of deducible. + 2) [fixed] The added constraint is same_type instead of deducible. I believe that while it's probably possible to construct a testcase that behaves differently with this simplification, it should have the same @@ -30079,7 +30080,7 @@ alias_ctad_tweaks (tree tmpl, tree uguides) /* 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_SAME, atype, ret); + tree same = finish_trait_expr (loc, CPTK_IS_DEDUCIBLE, tmpl, ret); ci = append_constraint (ci, same); } @@ -30093,12 +30094,7 @@ 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. */ - tree targs = make_tree_vec (natparms); - int err = unify (atparms, targs, utype, ret, UNIFY_ALLOW_NONE, false); - for (unsigned i = 0; !err && i < natparms; ++i) - if (TREE_VEC_ELT (targs, i) == NULL_TREE) - err = true; - if (err) + if (!type_targs_deducible_from (tmpl, ret)) continue; } @@ -30108,6 +30104,25 @@ alias_ctad_tweaks (tree tmpl, tree uguides) return aguides; } +/* True iff template arguments for TMPL can be deduced from TYPE. + Used to implement CPTK_IS_DEDUCIBLE for alias CTAD. */ + +bool +type_targs_deducible_from (tree tmpl, tree type) +{ + tree tparms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl); + int len = TREE_VEC_LENGTH (tparms); + tree targs = make_tree_vec (len); + if (unify (tparms, targs, TREE_TYPE (tmpl), type, + UNIFY_ALLOW_NONE, false)) + return false; + /* Maybe add in default template args. */ + targs = coerce_template_parms (tparms, targs, tmpl, tf_none); + if (targs == error_mark_node) + return false; + return constraints_satisfied_p (tmpl, targs); +} + /* Return artificial deduction guides built from the constructors of class template TMPL. */ diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 79b7cc72f21..9103f5de2f4 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -12048,6 +12048,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) case CPTK_REF_CONVERTS_FROM_TEMPORARY: return ref_xes_from_temporary (type1, type2, /*direct_init=*/false); + case CPTK_IS_DEDUCIBLE: + return type_targs_deducible_from (type1, type2); + #define DEFTRAIT_TYPE(CODE, NAME, ARITY) \ case CPTK_##CODE: #include "cp-trait.def" @@ -12205,6 +12208,14 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2) return error_mark_node; break; + case CPTK_IS_DEDUCIBLE: + if (!DECL_TYPE_TEMPLATE_P (type1)) + { + error ("%qD is not a class or alias template", type1); + return error_mark_node; + } + break; + #define DEFTRAIT_TYPE(CODE, NAME, ARITY) \ case CPTK_##CODE: #include "cp-trait.def" diff --git a/gcc/testsuite/g++.dg/ext/is_deducible1.C b/gcc/testsuite/g++.dg/ext/is_deducible1.C new file mode 100644 index 00000000000..857f59db4c8 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_deducible1.C @@ -0,0 +1,27 @@ +// { dg-do compile { target c++20 } } + +template struct A { }; +template struct B { }; + +// Simple forms. +static_assert (__is_deducible (::A, A)); +static_assert (__is_deducible (B, B)); +static_assert (!__is_deducible (A, B)); +static_assert (!__is_deducible (::B, A)); + +// This is the interesting use case for alias CTAD. +template using AP = A; +static_assert (__is_deducible (AP, A)); +static_assert (!__is_deducible (AP, A)); + +// Can't deduce a parameter not used on the RHS. +template using C = void; +static_assert (!__is_deducible (C, C)); + +// But a default template argument counts. +template using D = void; +static_assert (__is_deducible (D, D)); + +// We don't try to support this. +template void f(T); +bool b = __is_deducible (f, void (int)); // { dg-error "class or alias" } diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def index 823899a26c5..e43fb464f42 100644 --- a/gcc/cp/cp-trait.def +++ b/gcc/cp/cp-trait.def @@ -84,6 +84,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1) DEFTRAIT_EXPR (IS_UNION, "__is_union", 1) DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2) DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2) +DEFTRAIT_EXPR (IS_DEDUCIBLE, "__is_deducible", 2) DEFTRAIT_TYPE (REMOVE_CV, "__remove_cv", 1) DEFTRAIT_TYPE (REMOVE_REFERENCE, "__remove_reference", 1)