public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: unqualified member template in constraint [PR101247]
@ 2021-06-30 21:27 Patrick Palka
  2021-07-01 15:17 ` Jason Merrill
  0 siblings, 1 reply; 3+ messages in thread
From: Patrick Palka @ 2021-06-30 21:27 UTC (permalink / raw)
  To: gcc-patches

Here any_template_parm_r is failing to mark the template parameters
that're 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 unfortunately we still
crash on the commented out lines in the below testcase.  (The problem
there ultimately seems to be in push_template_decl, where we consider
the out-of-line definition of A::C to not be primary since
template_parm_scope_p is false, so DECL_PRIMARY_TEMPLATE never gets set.
Fixing that might not be safe enough to backport, but hopefully this
partial fix is.)

Bootstrapped and regtested on x86_64-pc-linux-gnu, also tested on
range-v3 and cmcstl2, does this look OK for trunk/11?

	PR c++/101247

gcc/cp/ChangeLog:

	* pt.c (any_template_parm_r) <case TEMPLATE_DECL>: 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.
---
 gcc/cp/pt.c                                   | 23 ++++-----------
 .../g++.dg/cpp2a/concepts-memtmpl4.C          | 28 +++++++++++++++++++
 2 files changed, 33 insertions(+), 18 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index db769d59951..a8fdd2e177e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10735,24 +10735,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 dtmpl = TREE_TYPE (INNERMOST_TEMPLATE_PARMS (ftpi->ctx_parms)))
+	  if (tree com = common_enclosing_class (DECL_CONTEXT (t),
+						 DECL_CONTEXT (dtmpl)))
+	    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 <typename> struct A {
+  template <typename c> static constexpr bool d = true;
+  struct B;
+  template <typename> struct C;
+};
+
+template <typename a>
+struct A<a>::B {
+  template <typename c> static void f(c) requires d<c>;
+};
+
+template <typename a>
+template <typename b>
+struct A<a>::C {
+  template <typename c> static void f(c) requires d<c>;
+  static void g() requires d<b>;
+};
+
+int main()
+{
+  A<void>::B::f(0);
+  A<void>::C<int>::f(0);
+  // A<void>::C<int>::g();
+}
-- 
2.32.0.93.g670b81a890


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] c++: unqualified member template in constraint [PR101247]
  2021-06-30 21:27 [PATCH] c++: unqualified member template in constraint [PR101247] Patrick Palka
@ 2021-07-01 15:17 ` Jason Merrill
  2021-07-01 15:33   ` Patrick Palka
  0 siblings, 1 reply; 3+ messages in thread
From: Jason Merrill @ 2021-07-01 15:17 UTC (permalink / raw)
  To: Patrick Palka, gcc-patches

On 6/30/21 5:27 PM, Patrick Palka wrote:
> Here any_template_parm_r is failing to mark the template parameters
> that're 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 unfortunately we still
> crash on the commented out lines in the below testcase.  (The problem
> there ultimately seems to be in push_template_decl, where we consider
> the out-of-line definition of A::C to not be primary since
> template_parm_scope_p is false, so DECL_PRIMARY_TEMPLATE never gets set.
> Fixing that might not be safe enough to backport, but hopefully this
> partial fix is.)
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, also tested on
> range-v3 and cmcstl2, does this look OK for trunk/11?

OK.  Are you looking at fixing the commented-out line in a separate patch?

> 	PR c++/101247
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.c (any_template_parm_r) <case TEMPLATE_DECL>: 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.
> ---
>   gcc/cp/pt.c                                   | 23 ++++-----------
>   .../g++.dg/cpp2a/concepts-memtmpl4.C          | 28 +++++++++++++++++++
>   2 files changed, 33 insertions(+), 18 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C
> 
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index db769d59951..a8fdd2e177e 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -10735,24 +10735,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 dtmpl = TREE_TYPE (INNERMOST_TEMPLATE_PARMS (ftpi->ctx_parms)))
> +	  if (tree com = common_enclosing_class (DECL_CONTEXT (t),
> +						 DECL_CONTEXT (dtmpl)))
> +	    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 <typename> struct A {
> +  template <typename c> static constexpr bool d = true;
> +  struct B;
> +  template <typename> struct C;
> +};
> +
> +template <typename a>
> +struct A<a>::B {
> +  template <typename c> static void f(c) requires d<c>;
> +};
> +
> +template <typename a>
> +template <typename b>
> +struct A<a>::C {
> +  template <typename c> static void f(c) requires d<c>;
> +  static void g() requires d<b>;
> +};
> +
> +int main()
> +{
> +  A<void>::B::f(0);
> +  A<void>::C<int>::f(0);
> +  // A<void>::C<int>::g();
> +}
> 


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] c++: unqualified member template in constraint [PR101247]
  2021-07-01 15:17 ` Jason Merrill
@ 2021-07-01 15:33   ` Patrick Palka
  0 siblings, 0 replies; 3+ messages in thread
From: Patrick Palka @ 2021-07-01 15:33 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Patrick Palka, gcc-patches

On Thu, 1 Jul 2021, Jason Merrill wrote:

> On 6/30/21 5:27 PM, Patrick Palka wrote:
> > Here any_template_parm_r is failing to mark the template parameters
> > that're 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 unfortunately we still
> > crash on the commented out lines in the below testcase.  (The problem
> > there ultimately seems to be in push_template_decl, where we consider
> > the out-of-line definition of A::C to not be primary since
> > template_parm_scope_p is false, so DECL_PRIMARY_TEMPLATE never gets set.
> > Fixing that might not be safe enough to backport, but hopefully this
> > partial fix is.)
> > 
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, also tested on
> > range-v3 and cmcstl2, does this look OK for trunk/11?
> 
> OK.  Are you looking at fixing the commented-out line in a separate patch?

Thanks a lot.  Yes, I'm going to try to make us set
DECL_PRIMARY_TEMPLATE (probably from push_template_decl) when defining a
class-scope class template out-of-line.

> 
> > 	PR c++/101247
> > 
> > gcc/cp/ChangeLog:
> > 
> > 	* pt.c (any_template_parm_r) <case TEMPLATE_DECL>: 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.
> > ---
> >   gcc/cp/pt.c                                   | 23 ++++-----------
> >   .../g++.dg/cpp2a/concepts-memtmpl4.C          | 28 +++++++++++++++++++
> >   2 files changed, 33 insertions(+), 18 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-memtmpl4.C
> > 
> > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> > index db769d59951..a8fdd2e177e 100644
> > --- a/gcc/cp/pt.c
> > +++ b/gcc/cp/pt.c
> > @@ -10735,24 +10735,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 dtmpl = TREE_TYPE (INNERMOST_TEMPLATE_PARMS
> > (ftpi->ctx_parms)))
> > +	  if (tree com = common_enclosing_class (DECL_CONTEXT (t),
> > +						 DECL_CONTEXT (dtmpl)))
> > +	    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 <typename> struct A {
> > +  template <typename c> static constexpr bool d = true;
> > +  struct B;
> > +  template <typename> struct C;
> > +};
> > +
> > +template <typename a>
> > +struct A<a>::B {
> > +  template <typename c> static void f(c) requires d<c>;
> > +};
> > +
> > +template <typename a>
> > +template <typename b>
> > +struct A<a>::C {
> > +  template <typename c> static void f(c) requires d<c>;
> > +  static void g() requires d<b>;
> > +};
> > +
> > +int main()
> > +{
> > +  A<void>::B::f(0);
> > +  A<void>::C<int>::f(0);
> > +  // A<void>::C<int>::g();
> > +}
> > 
> 
> 


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-07-01 15:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-30 21:27 [PATCH] c++: unqualified member template in constraint [PR101247] Patrick Palka
2021-07-01 15:17 ` Jason Merrill
2021-07-01 15:33   ` Patrick Palka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).