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.133.124]) by sourceware.org (Postfix) with ESMTPS id 12BD93858C74 for ; Mon, 28 Mar 2022 14:57:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 12BD93858C74 Received: from mail-qt1-f198.google.com (mail-qt1-f198.google.com [209.85.160.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-224-WXmXr6q6O4yJsyci0utQMg-1; Mon, 28 Mar 2022 10:57:07 -0400 X-MC-Unique: WXmXr6q6O4yJsyci0utQMg-1 Received: by mail-qt1-f198.google.com with SMTP id a24-20020ac81098000000b002e1e06a72aeso12388199qtj.6 for ; Mon, 28 Mar 2022 07:57:06 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=dmldBb3MYi5WTs4GwLaFsmAQuebCTcm5aGqjACSjsXs=; b=1oPik42z8LTCcJz9q+1roBlgrc3mdqJp1S6hQLPOjKxiE3E3sToK2QDYIZh6xi8+Gg mQnyfbTLOL9iCKY+qyghmlDA7Ltwx+WJqLXAK38a/MNYsPbMYPiXrOLEL49V0D20FuO9 XXvvmE80HVGu8RED/OO8ODCDM2QuEPOp9pwPiaoUuBQHZb3zZ6oH7f0/Jcwp/RQw3SWH KMvtXic1Q3yrX/bPhOj6R4XqUsSE2+kAefShr0f+Ko+OZ5AWEUYXph7R3cHsIz0Nmw/f XJDyUbHXDOtR+Ln74OuuwRTZAq8vX0IC2gOnqHsAGr+tk/78LSo+83ADssD4noSGWD6E BboQ== X-Gm-Message-State: AOAM5310pJ/p3xTraFTwzYlsrCOOx9hgqvwkgHxyL3CXiowGi5mIxhc2 m9E3Uz8ByzbEB8HFTLLD9bCVUvB4HRMIBqsJHiqVjuSfH1/vdjwj66igyapvtkZbuv9LgZv6FMP A4OnITze2aTnXipwtUAwhpNc208i8mhgaVJiUKxdqqgr2RRqIKvqrelQFS2vcu7SfOA== X-Received: by 2002:ad4:5ba3:0:b0:441:32c:767b with SMTP id 3-20020ad45ba3000000b00441032c767bmr20791230qvq.9.1648479421785; Mon, 28 Mar 2022 07:57:01 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzkauQu4ZXHx7LYDJH6df0VtIHAsFZZeTpPsfRsJUFRVwTTGHm1E2xxSnAu8E6q2zYdK0RZOw== X-Received: by 2002:ad4:5ba3:0:b0:441:32c:767b with SMTP id 3-20020ad45ba3000000b00441032c767bmr20791191qvq.9.1648479421332; Mon, 28 Mar 2022 07:57:01 -0700 (PDT) Received: from barrymore.redhat.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 e7-20020ac85987000000b002e1b7fa2201sm12427931qte.56.2022.03.28.07.56.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Mar 2022 07:57:00 -0700 (PDT) From: Jason Merrill To: gcc-patches@gcc.gnu.org Cc: Marek Polacek Subject: [pushed] c++: hash table ICE with variadic alias [PR105003] Date: Mon, 28 Mar 2022 10:56:58 -0400 Message-Id: <20220328145658.2789620-1-jason@redhat.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-13.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_LOW, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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-List-Received-Date: Mon, 28 Mar 2022 14:57:15 -0000 For PR104008 we thought it might be enough to keep strip_typedefs from removing this alias template specialization, but this PR demonstrates that other parts of the compiler also need to know to consider it dependent. So, this patch changes complex_alias_template_p to no longer consider template parameters used when their only use appears in a pack expansion, unless they are the parameter packs being expanded. To do that I also needed to change it to use cp_walk_tree instead of for_each_template_parm. It occurs to me that find_template_parameters should probably also use cp_walk_tree, but I'm not messing with that now. Tested x86_64-pc-linux-gnu, applying to trunk. PR c++/105003 PR c++/104008 PR c++/102869 gcc/cp/ChangeLog: * pt.cc (complex_alias_template_r): walk_tree callback, replacing uses_all_template_parms_r, complex_pack_expansion_r. (complex_alias_template_p): Adjust. * tree.cc (strip_typedefs): Revert r12-7710 change. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/variadic-alias6.C: New test. * g++.dg/cpp0x/variadic-alias7.C: New test. --- gcc/cp/pt.cc | 72 +++++++++++++------- gcc/cp/tree.cc | 13 +--- gcc/testsuite/g++.dg/cpp0x/variadic-alias6.C | 20 ++++++ gcc/testsuite/g++.dg/cpp0x/variadic-alias7.C | 16 +++++ 4 files changed, 85 insertions(+), 36 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-alias6.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-alias7.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 678063f6e4c..3df509bbed0 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -6460,10 +6460,7 @@ alias_template_specialization_p (const_tree t, return NULL_TREE; } -/* An alias template is complex from a SFINAE perspective if a template-id - using that alias can be ill-formed when the expansion is not, as with - the void_t template. We determine this by checking whether the - expansion for the alias template uses all its template parameters. */ +/* Data structure for complex_alias_template_*. */ struct uses_all_template_parms_data { @@ -6471,31 +6468,36 @@ struct uses_all_template_parms_data bool *seen; }; -static int -uses_all_template_parms_r (tree t, void *data_) +/* walk_tree callback for complex_alias_template_p. */ + +static tree +complex_alias_template_r (tree *tp, int *walk_subtrees, void *data_) { - struct uses_all_template_parms_data &data - = *(struct uses_all_template_parms_data*)data_; - tree idx = get_template_parm_index (t); + tree t = *tp; + auto &data = *(struct uses_all_template_parms_data*)data_; - if (TEMPLATE_PARM_LEVEL (idx) == data.level) - data.seen[TEMPLATE_PARM_IDX (idx)] = true; - return 0; -} + switch (TREE_CODE (t)) + { + case TEMPLATE_TYPE_PARM: + case TEMPLATE_PARM_INDEX: + case TEMPLATE_TEMPLATE_PARM: + case BOUND_TEMPLATE_TEMPLATE_PARM: + { + tree idx = get_template_parm_index (t); + if (TEMPLATE_PARM_LEVEL (idx) == data.level) + data.seen[TEMPLATE_PARM_IDX (idx)] = true; + } -/* for_each_template_parm any_fn callback for complex_alias_template_p. */ + default:; + } + + if (!PACK_EXPANSION_P (t)) + return 0; -static int -complex_pack_expansion_r (tree t, void *data_) -{ /* An alias template with a pack expansion that expands a pack from the enclosing class needs to be considered complex, to avoid confusion with the same pack being used as an argument to the alias's own template parameter (91966). */ - if (!PACK_EXPANSION_P (t)) - return 0; - struct uses_all_template_parms_data &data - = *(struct uses_all_template_parms_data*)data_; for (tree pack = PACK_EXPANSION_PARAMETER_PACKS (t); pack; pack = TREE_CHAIN (pack)) { @@ -6505,11 +6507,34 @@ complex_pack_expansion_r (tree t, void *data_) int idx, level; template_parm_level_and_index (parm_pack, &level, &idx); if (level < data.level) - return 1; + return t; + + /* Consider the expanded packs to be used outside the expansion... */ + data.seen[idx] = true; } + + /* ...but don't walk into the pattern. Consider PR104008: + + template + using IsOneOf = disjunction...>; + + where IsOneOf seemingly uses all of its template parameters in its + expansion (and does not expand a pack from the enclosing class), so the + alias was not marked as complex. However, if it is used like + "IsOneOf", the empty pack for Ts means that T no longer appears in the + expansion. So only Ts is considered used by the pack expansion. */ + *walk_subtrees = false; + return 0; } +/* An alias template is complex from a SFINAE perspective if a template-id + using that alias can be ill-formed when the expansion is not, as with + the void_t template. + + Returns 1 if always complex, 0 if not complex, -1 if complex iff any of the + template arguments are empty packs. */ + static bool complex_alias_template_p (const_tree tmpl) { @@ -6530,8 +6555,7 @@ complex_alias_template_p (const_tree tmpl) for (int i = 0; i < len; ++i) data.seen[i] = false; - if (for_each_template_parm (pat, uses_all_template_parms_r, &data, - NULL, true, complex_pack_expansion_r)) + if (cp_walk_tree_without_duplicates (&pat, complex_alias_template_r, &data)) return true; for (int i = 0; i < len; ++i) if (!data.seen[i]) diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 492921721f2..780a8d89165 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -1778,18 +1778,7 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags) if (TYPE_P (pat)) { type = strip_typedefs (pat, remove_attributes, flags); - /* Empty packs can thwart our efforts here. Consider - - template - using IsOneOf = disjunction...>; - - where IsOneOf seemingly uses all of its template parameters in - its expansion (and does not expand a pack from the enclosing - class), so the alias is not marked as complex. However, it may - be used as in "IsOneOf", where Ts is an empty parameter pack, - and stripping it down into "disjunction<>" here would exclude the - Ts pack, resulting in an error. */ - if (type != pat && uses_parameter_packs (type)) + if (type != pat) { result = build_distinct_type_copy (t); PACK_EXPANSION_PATTERN (result) = type; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-alias6.C b/gcc/testsuite/g++.dg/cpp0x/variadic-alias6.C new file mode 100644 index 00000000000..c095bc537d7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-alias6.C @@ -0,0 +1,20 @@ +// PR c++/105003 +// { dg-do compile { target c++11 } } + +template struct A; +template struct B { }; +template struct C { }; + +// Fn is not complex, since T is used outside the pack expansion, so the two +// partial specializations are equivalent. +template using Fn = T(Ts...); +template struct A*> { }; +template struct A { }; // { dg-error "redefinition" } + +// CB is complex, since T is only used in the pack expansion, so the two +// partial specializations are functionally equivalent but not equivalent. +template using CB = C...>; +template struct A*> { }; +template struct A...>*> { }; // IFNDR +A>*> a; // { dg-error "ambiguous" } +// { dg-prune-output "incomplete" } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-alias7.C b/gcc/testsuite/g++.dg/cpp0x/variadic-alias7.C new file mode 100644 index 00000000000..41a432a8e41 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-alias7.C @@ -0,0 +1,16 @@ +// PR c++/102869 +// { dg-do compile { target c++11 } } + +template struct integer_sequence; + +template +using make_index_sequence = integer_sequence<__integer_pack(_Num)...>; + +template struct Tuple; + +template using tuple_t = Tuple...>; + +template +void f() { + tuple_t t; +} base-commit: 19b87a06482756739087283cd8b884cb3de693f9 -- 2.27.0