From patchwork Sun Apr 19 16:55:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1272976 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=Py89Roi9; dkim-atps=neutral Received: from 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 RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 494wxR5G1wz9sP7 for ; Mon, 20 Apr 2020 02:55:41 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B404F385C426; Sun, 19 Apr 2020 16:55:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B404F385C426 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1587315335; bh=0+q+G+v8sF743R//ZuhnwuIzLpSi0IoVP4pRFulVDTs=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=Py89Roi9O3CxKg91L88lptMsUOEC5rYpFRHu5xO4hWszNy9vk3+Lv6o5B6nXhDzA3 l76JbhnZ4ak5ujDIb6MTSrp/1WBzmjWVKTP+uN2sA+1OUHU7ErRdKyHxJNqqAl37FO qMi0P3LwKhyfpkFJX3TcU4ZUQdddNCd4iFkJz1eU= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-1.mimecast.com (us-smtp-1.mimecast.com [205.139.110.61]) by sourceware.org (Postfix) with ESMTP id BBB51385C426 for ; Sun, 19 Apr 2020 16:55:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org BBB51385C426 Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-40-dG-QmUcyNlWDyxdWpzYnCA-1; Sun, 19 Apr 2020 12:55:29 -0400 X-MC-Unique: dG-QmUcyNlWDyxdWpzYnCA-1 Received: by mail-qk1-f198.google.com with SMTP id x8so7661206qkf.3 for ; Sun, 19 Apr 2020 09:55:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=+KREV8DIaHRdrYS8a2H1Tkydwwrolh1EHC7wU6KxTug=; b=JFgxkUoR1SSUfCD0yUG5AfbsN8E/rlWZrNPBabef7WY5AiHAwbPGv6Gx4osmgdoqH8 lbEMTAdGxCVII8ZCjzJ60uiEhmLCJRVsxN2bIXySAEfjmwcJyY+4cvhNshZo/2mIEfOW 9YLSJjq7yqXkpFgUz+cx2x6K11czq8dgQ0KELFK8F48mYyaxFbbvDKlM2OOMrqgA5wTT T3KNddO9TDhERVSBZGXVGIxKIWvhKaJgzL9gJB+y3wALaeRP9HCLx9IVrlCwuFNH2GU5 w34qbni6hbJ1cLZS17s5v+fBf0P+7AqRbZqR4hRerfqevyLye57K9m9gqcmwVmwmCG2b Lt2Q== X-Gm-Message-State: AGi0PuaYiL6C6NQ8/Fq8s7kxtquMyv9qBJVyeCE2gnDNymsD7NlnjvfL htyTnfaAiAz8xJxLB7bLvsuejrzqTcLmNvCiBtzzziGWieBV/NN5zCv5h/041yjvRMEVtqWUdz8 81wSZBVxJdGLAHKKSDQ== X-Received: by 2002:ac8:32cd:: with SMTP id a13mr12646612qtb.360.1587315328990; Sun, 19 Apr 2020 09:55:28 -0700 (PDT) X-Google-Smtp-Source: APiQypI7p84sFZTCLN67KNF9sVJhS1pLVLtkqyUH6zZpRJMei/pY4j102W/Wes16bc7VAeaL/DBpHA== X-Received: by 2002:ac8:32cd:: with SMTP id a13mr12646583qtb.360.1587315328660; Sun, 19 Apr 2020 09:55:28 -0700 (PDT) Received: from localhost.localdomain (ool-457d493a.dyn.optonline.net. [69.125.73.58]) by smtp.gmail.com with ESMTPSA id y52sm12365242qth.38.2020.04.19.09.55.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Apr 2020 09:55:28 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH] c++: Recursive unification with packs and explicit targs [PR94628] Date: Sun, 19 Apr 2020 12:55:24 -0400 Message-Id: <20200419165524.2005506-1-ppalka@redhat.com> X-Mailer: git-send-email 2.26.1.107.gefe3874640 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-28.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: Patrick Palka via Gcc-patches From: Patrick Palka Reply-To: Patrick Palka Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" This PR seems to be similar to PR c++/43382, except that the recursive call to the variadic function with trailing return type in this testcase is additionally given some explicit template arguments. In the first testcase below, when resolving the recursive call to 'select', fn_type_unification first substitutes in the call's explicit template arguments before doing unification, and so during this substitution the template argument pack for Args is incomplete. Since the pack is incomplete, the substitution of 'args...' in the trailing return type decltype(f(args...)) is handled by the unsubstituted_packs case of tsubst_pack_expansion. But the handling of this case happens _before_ we reset local_specializations, and so the substitution ends up reusing the old binding for 'args' from local_specializations rather than building a new one. This patch fixes this issue by setting up local_specializations sooner in tsubst_pack_expansion, before the handling of the unsubstituted_packs case. It also adds a new policy to local_specialization_stack so that we could use the class here to conditionally replace local_specializations. Passes 'make check-c++', does this look OK to commit after bootstrap/regtesting? gcc/cp/ChangeLog: PR c++/94628 * cp-tree.h (lss_policy::lss_inherit): New enumerator. * pt.c (local_specialization_stack::local_specialization_stack): Handle an lss_inherit policy. (local_specialization_stack::~local_specialization_stack): Likewise. (tsubst_pack_expansion): Use a local_specialization_stack instead of manually saving and restoring local_specializations. Conditionally replace local_specializations sooner, before the handling of the unsubstituted_packs case. gcc/testsuite/ChangeLog: PR c++/94628 * g++.dg/cpp0x/variadic179.C: New test. * g++.dg/cpp0x/variadic180.C: New test. --- gcc/cp/cp-tree.h | 2 +- gcc/cp/pt.c | 38 +++++++++++------------- gcc/testsuite/g++.dg/cpp0x/variadic179.C | 16 ++++++++++ gcc/testsuite/g++.dg/cpp0x/variadic180.C | 25 ++++++++++++++++ 4 files changed, 59 insertions(+), 22 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic179.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic180.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 000badc21ac..5b3b9507474 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5424,7 +5424,7 @@ enum unification_kind_t { // An RAII class used to create a new pointer map for local // specializations. When the stack goes out of scope, the // previous pointer map is restored. -enum lss_policy { lss_blank, lss_copy }; +enum lss_policy { lss_blank, lss_copy, lss_inherit }; class local_specialization_stack { public: diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 9e39f46a090..9cea663514d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -83,7 +83,9 @@ static tree cur_stmt_expr; local_specialization_stack::local_specialization_stack (lss_policy policy) : saved (local_specializations) { - if (policy == lss_blank || !saved) + if (policy == lss_inherit) + ; + else if (policy == lss_blank || !saved) local_specializations = new hash_map; else local_specializations = new hash_map(*saved); @@ -91,8 +93,11 @@ local_specialization_stack::local_specialization_stack (lss_policy policy) local_specialization_stack::~local_specialization_stack () { - delete local_specializations; - local_specializations = saved; + if (local_specializations != saved) + { + delete local_specializations; + local_specializations = saved; + } } /* True if we've recursed into fn_type_unification too many times. */ @@ -12694,7 +12699,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, bool unsubstituted_fn_pack = false; int i, len = -1; tree result; - hash_map *saved_local_specializations = NULL; bool need_local_specializations = false; int levels; @@ -12893,7 +12897,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, = build_extra_args (pattern, args, complain); return t; } - else if (unsubstituted_packs) + + /* If NEED_LOCAL_SPECIALIZATIONS then we're in a late-specified return + type, so create our own local specializations map; the current map is + either NULL or (in the case of recursive unification) might have + bindings that we don't want to use or alter. */ + local_specialization_stack lss (need_local_specializations + ? lss_blank : lss_inherit); + + if (unsubstituted_packs) { /* There were no real arguments, we're just replacing a parameter pack with another version of itself. Substitute into the @@ -12910,16 +12922,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, gcc_assert (len >= 0); - if (need_local_specializations) - { - /* We're in a late-specified return type, so create our own local - specializations map; the current map is either NULL or (in the - case of recursive unification) might have bindings that we don't - want to use or alter. */ - saved_local_specializations = local_specializations; - local_specializations = new hash_map; - } - /* For each argument in each argument pack, substitute into the pattern. */ result = make_tree_vec (len); @@ -12966,12 +12968,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, } } - if (need_local_specializations) - { - delete local_specializations; - local_specializations = saved_local_specializations; - } - /* If the dependent pack arguments were such that we end up with only a single pack expansion again, there's no need to keep it in a TREE_VEC. */ if (len == 1 && TREE_CODE (result) == TREE_VEC diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic179.C b/gcc/testsuite/g++.dg/cpp0x/variadic179.C new file mode 100644 index 00000000000..f04d3f753ca --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic179.C @@ -0,0 +1,16 @@ +// PR c++/94628 +// { dg-do compile { target c++11 } } + +int f(int, int); +int f(int); + +template +auto select(Args... args) -> decltype(f(args...)) +{ + if (sizeof...(Args) > 1) + return select(7); + else + return 0; +} + +int a = select(0, 1); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic180.C b/gcc/testsuite/g++.dg/cpp0x/variadic180.C new file mode 100644 index 00000000000..e8fcdd0a64d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic180.C @@ -0,0 +1,25 @@ +// PR c++/94628 +// A variant of variadic101.C where the recursive call to deref +// has its first template argument explicitly given. +// { dg-do compile { target c++11 } } + +template +struct Container +{ T f() const; }; + +template +T deref(const T& t) +{ return t; } + + +template +auto +deref(const T& u, int r, Args... args) +-> decltype(deref(u.f(), args...)) +{ return deref(u.f(), args...); } + +int main(void) +{ + Container> v; + deref(v,1,2); +}