From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1888) id 56C3E3848013; Fri, 2 Jul 2021 17:55:33 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 56C3E3848013 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Patrick Palka To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-1989] c++: unqualified member template in constraint [PR101247] X-Act-Checkin: gcc X-Git-Author: Patrick Palka X-Git-Refname: refs/heads/master X-Git-Oldrev: 42a9e4e1381ba14d8ef21b331494945c2f51e6be X-Git-Newrev: e3528ce197f8886869f95e8a8f901861a319851c Message-Id: <20210702175533.56C3E3848013@sourceware.org> Date: Fri, 2 Jul 2021 17:55:33 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 02 Jul 2021 17:55:33 -0000 https://gcc.gnu.org/g:e3528ce197f8886869f95e8a8f901861a319851c commit r12-1989-ge3528ce197f8886869f95e8a8f901861a319851c Author: Patrick Palka Date: Fri Jul 2 13:54:57 2021 -0400 c++: unqualified member template in constraint [PR101247] Here any_template_parm_r is failing to mark the template parameters implicitly used by the unqualified use of 'd' inside the constraint because the code to do so assumes each level of a template parameter list points to the corresponding primary template, but here the parameter level for A in the out-of-line definition of A::B does not (nor do the parameter levels for A and C in the definition of A::C), which causes us to overlook the sharing. So it seems we can't in general depend on the TREE_TYPE of a template parameter level being non-empty here. This patch partially fixes this by rewriting the relevant part of any_template_parm_r to not depend on the TREE_TYPE of outer levels. We still depend on the innermost level to point to the innermost primary template, so we still crash on the commented out line in the below testcase. PR c++/101247 gcc/cp/ChangeLog: * pt.c (any_template_parm_r) : Rewrite to use common_enclosing_class and to not depend on the TREE_TYPE of outer levels pointing to the corresponding primary template. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-memtmpl4.C: New test. Diff: --- gcc/cp/pt.c | 23 +++++---------------- gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C | 28 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index dda6c9e940d..7e56ccfc45f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10731,24 +10731,11 @@ any_template_parm_r (tree t, void *data) { /* If T is a member template that shares template parameters with ctx_parms, we need to mark all those parameters for mapping. */ - tree dparms = DECL_TEMPLATE_PARMS (t); - tree cparms = ftpi->ctx_parms; - while (TMPL_PARMS_DEPTH (dparms) > ftpi->max_depth) - dparms = TREE_CHAIN (dparms); - while (TMPL_PARMS_DEPTH (cparms) > TMPL_PARMS_DEPTH (dparms)) - cparms = TREE_CHAIN (cparms); - while (dparms - && (TREE_TYPE (TREE_VALUE (dparms)) - != TREE_TYPE (TREE_VALUE (cparms)))) - dparms = TREE_CHAIN (dparms), - cparms = TREE_CHAIN (cparms); - if (dparms) - { - int ddepth = TMPL_PARMS_DEPTH (dparms); - tree dargs = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (t))); - for (int i = 0; i < ddepth; ++i) - WALK_SUBTREE (TMPL_ARGS_LEVEL (dargs, i+1)); - } + if (tree ctmpl = TREE_TYPE (INNERMOST_TEMPLATE_PARMS (ftpi->ctx_parms))) + if (tree com = common_enclosing_class (DECL_CONTEXT (t), + DECL_CONTEXT (ctmpl))) + if (tree ti = CLASSTYPE_TEMPLATE_INFO (com)) + WALK_SUBTREE (TI_ARGS (ti)); } break; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C b/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C new file mode 100644 index 00000000000..625149e5025 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C @@ -0,0 +1,28 @@ +// PR c++/101247 +// { dg-do compile { target concepts } } +// A variant of concepts-memtmpl3.C where f is defined outside A's definition. + +template struct A { + template static constexpr bool d = true; + struct B; + template struct C; +}; + +template +struct A::B { + template static void f(c) requires d; +}; + +template +template +struct A::C { + template static void f(c) requires d; + static void g() requires d; +}; + +int main() +{ + A::B::f(0); + A::C::f(0); + // A::C::g(); +}