[PATCH] c++: unqualified member template in constraint [PR101247]

Patrick Palka ppalka@redhat.com
Thu Jul 1 15:33:07 GMT 2021


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();
> > +}
> > 
> 
> 



More information about the Gcc-patches mailing list